4 Commits

Author SHA1 Message Date
4f1d19fcbd upgrade kotlin version to 1.9.22 2024-02-24 16:25:31 +08:00
9a85e4d537 replace all group_id and user_id to Long 2024-02-24 16:25:31 +08:00
fac92d8094 Merge remote-tracking branch 'origin/master' 2024-02-24 12:32:02 +08:00
605f58da47 Shamrock: Using the NT kernel to upload resources
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-24 12:31:51 +08:00
63 changed files with 474 additions and 391 deletions

View File

@ -17,7 +17,7 @@ android {
minSdk = 27
targetSdk = 34
versionCode = getVersionCode()
versionName = "1.0.8" + ".r${getGitCommitCount()}." + getVersionName()
versionName = "1.0.9" + ".r${getGitCommitCount()}." + getVersionName()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@ -92,7 +92,7 @@ android {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.4"
kotlinCompilerExtensionVersion = "1.5.10"
}
packaging {
jniLibs {
@ -127,11 +127,6 @@ android {
}
configureAppSigningConfigsForRelease(project)
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
}
fun configureAppSigningConfigsForRelease(project: Project) {

View File

@ -39,7 +39,6 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
md5.cpp
cqcode.cpp
silk.cpp
group_honor.cpp
message.cpp
shamrock.cpp)

View File

@ -299,6 +299,16 @@ object ShamrockConfig {
return preferences.getBoolean("enable_self_msg", false)
}
fun enableOldBDH(ctx: Context): Boolean {
val preferences = ctx.getSharedPreferences("config", 0)
return preferences.getBoolean("enable_old_bdh", false)
}
fun setEnableOldBDH(ctx: Context, v: Boolean) {
val preferences = ctx.getSharedPreferences("config", 0)
preferences.edit().putBoolean("enable_old_bdh", v).apply()
}
fun enableSyncMsgAsSentMsg(ctx: Context): Boolean {
val preferences = ctx.getSharedPreferences("config", 0)
return preferences.getBoolean("enable_sync_msg_as_sent_msg", false)
@ -334,7 +344,6 @@ object ShamrockConfig {
"inject_packet" to preferences.getBoolean("inject_packet", false),
"debug" to preferences.getBoolean("debug", false),
"anti_qq_trace" to preferences.getBoolean("anti_qq_trace", true),
//"auto_clear" to preferences.getBoolean("auto_clear", false),
"ssl_private_pwd" to preferences.getString("ssl_private_pwd", ""),
"key_store" to preferences.getString("key_store", ""),
"enable_self_msg" to preferences.getBoolean("enable_self_msg", false),
@ -343,7 +352,8 @@ object ShamrockConfig {
"alive_reply" to preferences.getBoolean("alive_reply", false),
"enable_sync_msg_as_sent_msg" to preferences.getBoolean("enable_sync_msg_as_sent_msg", false),
"disable_auto_sync_setting" to preferences.getBoolean("disable_auto_sync_setting", false),
"forbid_useless_process" to preferences.getBoolean("forbid_useless_process", false)
"forbid_useless_process" to preferences.getBoolean("forbid_useless_process", false),
"enable_old_bdh" to preferences.getBoolean("enable_old_bdh", false),
)
}

View File

@ -102,7 +102,7 @@ fun LabFragment() {
Function(
title = "禁止无用进程",
desc = "禁止QQ生成无用进程浪费内存",
desc = "禁止QQ生成无用进程浪费内存,可能造成部分功能闪退。",
descColor = color,
isSwitch = ShamrockConfig.isForbidUselessProcess(ctx)
) {
@ -221,7 +221,7 @@ fun LabFragment() {
}.onSuccess {
Function(
title = "反检测加强",
desc = "可能导致某些设备频繁闪退",
desc = "可能导致某些设备频繁闪退,将拦截环境包上报。",
descColor = color,
isSwitch = it.getBoolean("super_anti", false)
) { v ->
@ -295,17 +295,16 @@ fun LabFragment() {
return@Function true
}
/*
Function(
title = "使用纯数字ECHO",
desc = "在部分强类型语言框架,需要打开开关。",
title = "启用旧版资源上传系统",
desc = "如果NT内核无法上传资源打开开关。",
descColor = it,
isSwitch = ShamrockConfig.isEchoNumber(ctx)
isSwitch = ShamrockConfig.enableOldBDH(ctx)
) {
ShamrockConfig.setEchoNumber(ctx, it)
ShamrockConfig.setEnableOldBDH(ctx, it)
ShamrockConfig.pushUpdate(ctx)
return@Function true
}*/
}
}
}
}

View File

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.2.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.20" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
id("com.android.library") version "8.2.0" apply false
}

View File

@ -26,7 +26,7 @@ buildscript {
}
}
dependencies {
classpath("com.android.tools:r8:8.2.26")
classpath("com.android.tools:r8:8.2.47")
}
}

View File

@ -88,16 +88,16 @@ internal object CardSvc: BaseSvc() {
return rsp.signed_ark_msg.get()
}
suspend fun getProfileCard(uin: String): Result<Card> {
suspend fun getProfileCard(uin: Long): Result<Card> {
return getProfileCardFromCache(uin).onFailure {
return refreshAndGetProfileCard(uin)
}
}
fun getProfileCardFromCache(uin: String): Result<Card> {
fun getProfileCardFromCache(uin: Long): Result<Card> {
val profileDataService = app
.getRuntimeService(IProfileDataService::class.java, "all")
val card = profileDataService.getProfileCard(uin, true)
val card = profileDataService.getProfileCard(uin.toString(), true)
return if (card == null || card.strNick.isNullOrEmpty()) {
Result.failure(Exception("unable to fetch profile card"))
} else {
@ -105,7 +105,7 @@ internal object CardSvc: BaseSvc() {
}
}
suspend fun refreshAndGetProfileCard(uin: String): Result<Card> {
suspend fun refreshAndGetProfileCard(uin: Long): Result<Card> {
val dataService = app
.getRuntimeService(IProfileDataService::class.java, "all")
val card = refreshCardLock.withLock {
@ -122,7 +122,7 @@ internal object CardSvc: BaseSvc() {
}
})
app.getRuntimeService(IProfileProtocolService::class.java, "all")
.requestProfileCard(app.currentUin, uin, 12, 0L, 0.toByte(), 0L, 0L, null, "", 0L, 10004, null, 0.toByte())
.requestProfileCard(app.currentUin, uin.toString(), 12, 0L, 0.toByte(), 0L, 0L, null, "", 0L, 10004, null, 0.toByte())
}
}
return if (card == null || card.strNick.isNullOrEmpty()) {

View File

@ -23,7 +23,7 @@ import protobuf.group_file_common.FolderInfo as GroupFileCommonFolderInfo
import protobuf.auto.toByteArray
internal object FileSvc: BaseSvc() {
suspend fun createFileFolder(groupId: String, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> {
suspend fun createFileFolder(groupId: Long, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> {
val data = Oidb0x6d7ReqBody(
createFolder = CreateFolderReq(
groupCode = groupId.toULong(),
@ -45,7 +45,7 @@ internal object FileSvc: BaseSvc() {
return Result.success(rsp.createFolder!!.folderInfo!!)
}
suspend fun deleteGroupFolder(groupId: String, folderUid: String): Boolean {
suspend fun deleteGroupFolder(groupId: Long, folderUid: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
deleteFolder = DeleteFolderReq(
groupCode = groupId.toULong(),
@ -59,7 +59,7 @@ internal object FileSvc: BaseSvc() {
return rsp.deleteFolder?.retCode == 0
}
suspend fun moveGroupFolder(groupId: String, folderUid: String, newParentFolderUid: String): Boolean {
suspend fun moveGroupFolder(groupId: Long, folderUid: String, newParentFolderUid: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, Oidb0x6d7ReqBody(
moveFolder = MoveFolderReq(
groupCode = groupId.toULong(),
@ -74,7 +74,7 @@ internal object FileSvc: BaseSvc() {
return rsp.moveFolder?.retCode == 0
}
suspend fun renameFolder(groupId: String, folderUid: String, name: String): Boolean {
suspend fun renameFolder(groupId: Long, folderUid: String, name: String): Boolean {
val buffer = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
renameFolder = RenameFolderReq(
groupCode = groupId.toULong(),
@ -89,10 +89,10 @@ internal object FileSvc: BaseSvc() {
return rsp.renameFolder?.retCode == 0
}
suspend fun deleteGroupFile(groupId: String, bizId: Int, fileUid: String): Boolean {
suspend fun deleteGroupFile(groupId: Long, bizId: Int, fileUid: String): Boolean {
val oidb0x6d6ReqBody = oidb_0x6d6.ReqBody().apply {
delete_file_req.set(oidb_0x6d6.DeleteFileReqBody().apply {
uint64_group_code.set(groupId.toLong())
uint64_group_code.set(groupId)
uint32_app_id.set(3)
uint32_bus_id.set(bizId)
str_parent_folder_id.set("/")

View File

@ -156,18 +156,18 @@ internal object GroupSvc: BaseSvc() {
})
}
fun poke(groupId: String, userId: String) {
fun poke(groupId: Long, userId: Long) {
val req = oidb_cmd0xed3.ReqBody().apply {
uint64_group_code.set(groupId.toLong())
uint64_to_uin.set(userId.toLong())
uint64_group_code.set(groupId)
uint64_to_uin.set(userId)
uint32_msg_seq.set(0)
}
sendOidb("OidbSvc.0xed3", 3795, 1, req.toByteArray())
}
suspend fun getGroupMemberList(groupId: String, refresh: Boolean): Result<List<TroopMemberInfo>> {
suspend fun getGroupMemberList(groupId: Long, refresh: Boolean): Result<List<TroopMemberInfo>> {
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
var memberList = service.getAllTroopMembers(groupId)
var memberList = service.getAllTroopMembers(groupId.toString())
if (refresh || memberList == null) {
memberList = requestTroopMemberInfo(service, groupId).onFailure {
return Result.failure(Exception("获取群成员列表失败"))
@ -227,26 +227,26 @@ internal object GroupSvc: BaseSvc() {
} ?: Result.failure(Exception("获取群信息超时"))
}
suspend fun getGroupInfo(groupId: String, refresh: Boolean): Result<TroopInfo> {
suspend fun getGroupInfo(groupId: Long, refresh: Boolean): Result<TroopInfo> {
val service = app
.getRuntimeService(ITroopInfoService::class.java, "all")
val groupInfo = getGroupInfo(groupId)
return if(refresh || !service.isTroopCacheInited || groupInfo.troopuin.isNullOrBlank()) {
requestGroupInfo(service, groupId.toLong())
requestGroupInfo(service, groupId)
} else {
Result.success(groupInfo)
}
}
suspend fun setGroupUniqueTitle(groupId: String, userId: String, title: String) {
suspend fun setGroupUniqueTitle(groupId: Long, userId: Long, title: String) {
val localMemberInfo = getTroopMemberInfoByUin(groupId, userId, true).getOrThrow()
val req = Oidb_0x8fc.ReqBody()
req.uint64_group_code.set(groupId.toLong())
req.uint64_group_code.set(groupId)
val memberInfo = Oidb_0x8fc.MemberInfo()
memberInfo.uint64_uin.set(userId.toLong())
memberInfo.uint64_uin.set(userId)
memberInfo.bytes_uin_name.set(ByteStringMicro.copyFromUtf8(localMemberInfo.troopnick.ifEmpty {
localMemberInfo.troopremark.ifNullOrEmpty("")
}))
@ -371,17 +371,17 @@ internal object GroupSvc: BaseSvc() {
sendOidb("OidbSvc.0x8a0_0", 2208, 0, reqBody.toByteArray())
}
fun getGroupInfo(groupId: String): TroopInfo {
fun getGroupInfo(groupId: Long): TroopInfo {
val runtime = AppRuntimeFetcher.appRuntime as QQAppInterface
val service = runtime
.getRuntimeService(ITroopInfoService::class.java, "all")
return service.getTroopInfo(groupId)
return service.getTroopInfo(groupId.toString())
}
fun getAdminList(
groupId: String,
groupId: Long,
withOwner: Boolean = false
): List<Long> {
val groupInfo = getGroupInfo(groupId)
@ -399,39 +399,39 @@ internal object GroupSvc: BaseSvc() {
suspend fun getMemberRole(groupId: Long, memberUin: Long): MemberRole {
if (!GET_MEMBER_ROLE_BY_NT) {
return when (memberUin) {
getOwner(groupId.toString()) -> MemberRole.Owner
in getAdminList(groupId.toString()) -> MemberRole.Admin
getOwner(groupId) -> MemberRole.Owner
in getAdminList(groupId) -> MemberRole.Admin
else -> MemberRole.Member
}
}
return when(getTroopMemberInfoByUinViaNt(groupId.toString(), memberUin, 3000).getOrNull()?.role) {
return when(getTroopMemberInfoByUinViaNt(groupId, memberUin, 3000).getOrNull()?.role) {
com.tencent.qqnt.kernel.nativeinterface.MemberRole.STRANGER -> MemberRole.Stranger
com.tencent.qqnt.kernel.nativeinterface.MemberRole.MEMBER -> MemberRole.Member
com.tencent.qqnt.kernel.nativeinterface.MemberRole.ADMIN -> MemberRole.Admin
com.tencent.qqnt.kernel.nativeinterface.MemberRole.OWNER -> MemberRole.Owner
com.tencent.qqnt.kernel.nativeinterface.MemberRole.UNSPECIFIED, null -> when (memberUin) {
getOwner(groupId.toString()) -> MemberRole.Owner
in getAdminList(groupId.toString()) -> MemberRole.Admin
getOwner(groupId) -> MemberRole.Owner
in getAdminList(groupId) -> MemberRole.Admin
else -> MemberRole.Member
}
}
}
fun getOwner(groupId: String): Long {
fun getOwner(groupId: Long): Long {
val groupInfo = getGroupInfo(groupId)
return groupInfo.troopowneruin?.toLong() ?: 0
}
fun isOwner(groupId: String): Boolean {
fun isOwner(groupId: Long): Boolean {
val groupInfo = getGroupInfo(groupId)
return groupInfo.troopowneruin == app.account
}
fun isAdmin(groupId: String): Boolean {
fun isAdmin(groupId: Long): Boolean {
val service = app
.getRuntimeService(ITroopInfoService::class.java, "all")
val groupInfo = service.getTroopInfo(groupId)
val groupInfo = service.getTroopInfo(groupId.toString())
return groupInfo.isAdmin || groupInfo.troopowneruin == app.account
}
@ -444,7 +444,7 @@ internal object GroupSvc: BaseSvc() {
}
}
fun modifyTroopName(groupId: String, name: String) {
fun modifyTroopName(groupId: Long, name: String) {
val businessHandler = app.getBusinessHandler(BusinessHandlerFactory.TROOP_MODIFY_HANDLER)
if (!GroupSvc::METHOD_REQ_MODIFY_GROUP_NAME.isInitialized) {
@ -535,17 +535,17 @@ internal object GroupSvc: BaseSvc() {
}
suspend fun getTroopMemberInfoByUin(
groupId: String,
uin: String,
groupId: Long,
uin: Long,
refresh: Boolean = false
): Result<TroopMemberInfo> {
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
var info = service.getTroopMember(groupId, uin)
if (refresh || !service.isMemberInCache(groupId, uin) || info == null || info.troopnick == null) {
info = requestTroopMemberInfo(service, groupId.toLong(), uin.toLong()).getOrNull()
var info = service.getTroopMember(groupId.toString(), uin.toString())
if (refresh || !service.isMemberInCache(groupId.toString(), uin.toString()) || info == null || info.troopnick == null) {
info = requestTroopMemberInfo(service, groupId, uin).getOrNull()
}
if (info == null) {
info = getTroopMemberInfoByUinViaNt(groupId, uin.toLong()).getOrNull()?.let {
info = getTroopMemberInfoByUinViaNt(groupId, uin).getOrNull()?.let {
TroopMemberInfo().apply {
troopnick = it.cardName
friendnick = it.nick
@ -555,7 +555,7 @@ internal object GroupSvc: BaseSvc() {
try {
if (info != null && (info.alias == null || info.alias.isBlank())) {
val req = group_member_info.ReqBody()
req.uint64_group_code.set(groupId.toLong())
req.uint64_group_code.set(groupId)
req.uint64_uin.set(uin.toLong())
req.bool_new_client.set(true)
req.uint32_client_type.set(1)
@ -590,17 +590,17 @@ internal object GroupSvc: BaseSvc() {
}
suspend fun getTroopMemberInfoByUinV2(
groupId: String,
uin: String,
groupId: Long,
uin: Long,
refresh: Boolean = false
): Result<TroopMemberInfo> {
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
var info = service.getTroopMember(groupId, uin)
if (refresh || !service.isMemberInCache(groupId, uin) || info == null || info.troopnick == null) {
info = requestTroopMemberInfo(service, groupId.toLong(), uin.toLong(), timeout = 2000).getOrNull()
var info = service.getTroopMember(groupId.toString(), uin.toString())
if (refresh || !service.isMemberInCache(groupId.toString(), uin.toString()) || info == null || info.troopnick == null) {
info = requestTroopMemberInfo(service, groupId, uin, timeout = 2000).getOrNull()
}
if (info == null) {
info = getTroopMemberInfoByUinViaNt(groupId, uin.toLong(), timeout = 2000L).getOrNull()?.let {
info = getTroopMemberInfoByUinViaNt(groupId, uin, timeout = 2000L).getOrNull()?.let {
TroopMemberInfo().apply {
troopnick = it.cardName
friendnick = it.nick
@ -610,8 +610,8 @@ internal object GroupSvc: BaseSvc() {
try {
if (info != null && (info.alias == null || info.alias.isBlank())) {
val req = group_member_info.ReqBody()
req.uint64_group_code.set(groupId.toLong())
req.uint64_uin.set(uin.toLong())
req.uint64_group_code.set(groupId)
req.uint64_uin.set(uin)
req.bool_new_client.set(true)
req.uint32_client_type.set(1)
req.uint32_rich_card_name_ver.set(1)
@ -645,7 +645,7 @@ internal object GroupSvc: BaseSvc() {
}
suspend fun getTroopMemberInfoByUinViaNt(
groupId: String,
groupId: Long,
qq: Long,
timeout: Long = 5000L
): Result<MemberInfo> {
@ -655,7 +655,7 @@ internal object GroupSvc: BaseSvc() {
val groupService = sessionService.groupService
val info = withTimeoutOrNull(timeout) {
suspendCancellableCoroutine {
groupService.getTransferableMemberInfo(groupId.toLong()) { code, _, data ->
groupService.getTransferableMemberInfo(groupId) { code, _, data ->
if (code != 0) {
it.resume(null)
return@getTransferableMemberInfo
@ -703,16 +703,16 @@ internal object GroupSvc: BaseSvc() {
}
}
private suspend fun requestTroopMemberInfo(service: ITroopMemberInfoService, groupId: String): Result<List<TroopMemberInfo>> {
private suspend fun requestTroopMemberInfo(service: ITroopMemberInfoService, groupId: Long): Result<List<TroopMemberInfo>> {
val info = RefreshTroopMemberListLock.withLock {
service.deleteTroopMembers(groupId)
service.deleteTroopMembers(groupId.toString())
refreshTroopMemberList(groupId)
withTimeoutOrNull(10000) {
var memberList: List<TroopMemberInfo>?
do {
delay(100)
memberList = service.getAllTroopMembers(groupId)
memberList = service.getAllTroopMembers(groupId.toString())
} while (memberList.isNullOrEmpty())
return@withTimeoutOrNull memberList
}
@ -745,7 +745,7 @@ internal object GroupSvc: BaseSvc() {
}
}
private fun refreshTroopMemberList(groupId: String) {
private fun refreshTroopMemberList(groupId: Long) {
val app = AppRuntimeFetcher.appRuntime
if (app !is AppInterface)
throw RuntimeException("AppRuntime cannot cast to AppInterface")
@ -763,7 +763,7 @@ internal object GroupSvc: BaseSvc() {
}
}
METHOD_REQ_TROOP_MEM_LIST.invoke(businessHandler, true, groupId, groupUin2GroupCode(groupId.toLong()).toString(), 5)
METHOD_REQ_TROOP_MEM_LIST.invoke(businessHandler, true, groupId, groupUin2GroupCode(groupId).toString(), 5)
}
private fun refreshTroopList() {

View File

@ -31,7 +31,7 @@ import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
internal object MsgSvc : BaseSvc() {
suspend fun prepareTempChatFromGroup(
private suspend fun prepareTempChatFromGroup(
groupId: String,
peerId: String
): Result<Unit> {

View File

@ -78,7 +78,7 @@ internal object VisitorSvc: BaseSvc() {
if(count !in 1 .. 20) {
return Result.failure(IllegalArgumentException("vote count must be in 1 .. 20"))
}
val card = CardSvc.getProfileCard(target.toString()).onFailure {
val card = CardSvc.getProfileCard(target).onFailure {
return Result.failure(RuntimeException("unable to fetch contact info"))
}.getOrThrow()
sendExtra("VisitorSvc.ReqFavorite") {

View File

@ -111,7 +111,7 @@ internal object MessageElementMaker {
else -> {
qq = qqStr.toLong()
type = 0
"@" + (data["name"].asStringOrNull ?: GroupSvc.getTroopMemberInfoByUinV2(peerId, qqStr, true)
"@" + (data["name"].asStringOrNull ?: GroupSvc.getTroopMemberInfoByUinV2(peerId.toLong(), qq, true)
.let {
val info = it.getOrNull()
if (info == null)
@ -138,11 +138,11 @@ internal object MessageElementMaker {
MsgConstant.KCHATTYPEC2C -> {
data.checkAndThrow("qq")
val qq = data["qq"].asString
val qq = data["qq"].asLong
val display =
"@" + (data["name"].asStringOrNull ?: CardSvc.getProfileCard(qq)
.onSuccess {
it.strNick.ifNullOrEmpty(qq)
it.strNick.ifNullOrEmpty(qq.toString())
}.onFailure {
LogCenter.log("无法获取QQ信息: $qq", Level.WARN)
})

View File

@ -37,6 +37,7 @@ import moe.fuqiuluo.shamrock.helper.LogicException
import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.helper.MusicHelper
import moe.fuqiuluo.shamrock.helper.ParamsException
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
import moe.fuqiuluo.shamrock.tools.*
import moe.fuqiuluo.shamrock.utils.AudioUtils
import moe.fuqiuluo.shamrock.utils.FileUtils
@ -91,7 +92,12 @@ internal object MsgElementMaker {
operator fun get(type: String): IMsgElementMaker? = makerMap[type]
private suspend fun createInlineKeywordElem(chatType: Int, msgId: Long, peerId: String, data: JsonObject): Result<MsgElement> {
private suspend fun createInlineKeywordElem(
chatType: Int,
msgId: Long,
peerId: String,
data: JsonObject
): Result<MsgElement> {
fun tryNewKeyboardButton(btn: JsonObject): InlineKeyboardButton {
return runCatching {
InlineKeyboardButton(
@ -126,6 +132,7 @@ internal object MsgElementMaker {
)
}
}
val elem = MsgElement()
elem.elementType = MsgConstant.KELEMTYPEINLINEKEYBOARD
val rows = arrayListOf<InlineKeyboardRow>()
@ -289,7 +296,7 @@ internal object MsgElementMaker {
data: JsonObject
): Result<MsgElement> {
data.checkAndThrow("id")
GroupSvc.poke(peerId, data["id"].asString)
GroupSvc.poke(peerId.toLong(), data["id"].asLong)
return Result.failure(ActionMsgException)
}
@ -715,11 +722,13 @@ internal object MsgElementMaker {
AudioUtils.obtainVideoCover(file.absolutePath, thumbPath!!)
}
Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId)
else -> error("Not supported chatType($chatType) for VideoMsg")
} trans VideoResource(file, File(thumbPath.toString()))
if (ShamrockConfig.enableOldBDH()) {
Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId)
else -> error("Not supported chatType($chatType) for VideoMsg")
} trans VideoResource(file, File(thumbPath.toString()))
}
video.fileTime = AudioUtils.getVideoTime(file)
video.fileSize = file.length()
@ -746,10 +755,10 @@ internal object MsgElementMaker {
data.checkAndThrow("qq")
val elem = MsgElement()
val qq = data["qq"].asString
val qqStr = data["qq"].asString
val at = TextElement()
when (qq) {
when (qqStr) {
"0", "all" -> {
at.content = "@全体成员"
at.atType = MsgConstant.ATTYPEALL
@ -770,25 +779,26 @@ internal object MsgElementMaker {
}
else -> {
val qq = qqStr.toLong()
val name = data["name"].asStringOrNull
if (name == null) {
val info = GroupSvc.getTroopMemberInfoByUinV2(peerId, qq, true).onFailure {
LogCenter.log("无法获取群成员信息: $qq", Level.ERROR)
val info = GroupSvc.getTroopMemberInfoByUinV2(peerId.toLong(), qq, true).onFailure {
LogCenter.log("无法获取群成员信息: $qqStr", Level.ERROR)
}.getOrNull()
if (info != null) {
at.content = "@${
info.troopnick
.ifNullOrEmpty(info.friendnick)
.ifNullOrEmpty(qq)
.ifNullOrEmpty(qqStr)
}"
} else {
at.content = "@$qq"
at.content = "@$qqStr"
}
} else {
at.content = "@$name"
}
at.atType = MsgConstant.ATTYPEONE
at.atNtUid = ContactHelper.getUidByUinAsync(qq.toLong())
at.atNtUid = ContactHelper.getUidByUinAsync(qq)
}
}
@ -849,36 +859,55 @@ internal object MsgElementMaker {
else -> {
LogCenter.log({ "Audio To SILK: $file" }, Level.DEBUG)
val result = AudioUtils.audioToSilk(file)
ptt.duration = result.first
ptt.duration = runCatching {
QRoute.api(IAIOPttApi::class.java)
.getPttFileDuration(result.second.absolutePath)
}.getOrElse {
result.first
}
file = result.second
ptt.formatType = MsgConstant.KPTTFORMATTYPESILK
}
}
//val msgService = NTServiceFetcher.kernelService.msgService!!
//val originalPath = msgService.getRichMediaFilePathForMobileQQSend(RichMediaFilePathInfo(
// MsgConstant.KELEMTYPEPTT, 0, ptt.md5HexStr, file.name, 1, 0, null, "", true
//))!!
//if (!QQNTWrapperUtil.CppProxy.fileIsExist(originalPath) || QQNTWrapperUtil.CppProxy.getFileSize(originalPath) != file.length()) {
// QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, originalPath)
//}
if (!(Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId)
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> Private(peerId)
else -> error("Not supported chatType($chatType) for RecordMsg")
} trans VoiceResource(file))
) {
return Result.failure(RuntimeException("上传语音失败: $file"))
}
val elem = MsgElement()
elem.elementType = MsgConstant.KELEMTYPEPTT
ptt.md5HexStr = QQNTWrapperUtil.CppProxy.genFileMd5Hex(file.absolutePath)
ptt.fileName = file.name
ptt.filePath = file.absolutePath
ptt.fileSize = file.length()
if (ShamrockConfig.enableOldBDH()) {
if (!(Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId)
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> Private(peerId)
else -> error("Not supported chatType($chatType) for RecordMsg")
} trans VoiceResource(file))
) {
return Result.failure(RuntimeException("上传语音失败: $file"))
}
ptt.filePath = file.absolutePath
} else {
val msgService = NTServiceFetcher.kernelService.msgService!!
val originalPath = msgService.getRichMediaFilePathForMobileQQSend(
RichMediaFilePathInfo(
MsgConstant.KELEMTYPEPTT, 0, ptt.md5HexStr, file.name, 1, 0, null, "", true
)
)
if (!QQNTWrapperUtil.CppProxy.fileIsExist(originalPath) || QQNTWrapperUtil.CppProxy.getFileSize(originalPath) != file.length()) {
QQNTWrapperUtil.CppProxy.copyFile(file.absolutePath, originalPath)
}
if (originalPath != null) {
ptt.filePath = originalPath
} else {
ptt.filePath = file.absolutePath
}
}
ptt.canConvert2Text = true
ptt.fileId = 0
ptt.fileUuid = ""
ptt.text = ""
if (!isMagic) {
ptt.voiceType = MsgConstant.KPTTVOICETYPESOUNDRECORD
@ -888,11 +917,6 @@ internal object MsgElementMaker {
ptt.voiceChangeType = MsgConstant.KPTTVOICECHANGETYPEECHO
}
ptt.canConvert2Text = false
ptt.fileId = 0
ptt.fileUuid = ""
ptt.text = ""
elem.pttElement = ptt
return Result.success(elem)
@ -927,11 +951,13 @@ internal object MsgElementMaker {
}
requireNotNull(file)
Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId)
else -> error("Not supported chatType($chatType) for PictureMsg")
} trans PictureResource(file)
if (ShamrockConfig.enableOldBDH()) {
Transfer with when (chatType) {
MsgConstant.KCHATTYPEGROUP -> Troop(peerId)
MsgConstant.KCHATTYPEC2C -> Private(peerId)
else -> error("Not supported chatType($chatType) for PictureMsg")
} trans PictureResource(file)
}
val elem = MsgElement()
elem.elementType = MsgConstant.KELEMTYPEPIC

View File

@ -0,0 +1,63 @@
package moe.fuqiuluo.shamrock.helper
import moe.fuqiuluo.shamrock.remote.service.data.GroupMemberHonor
object TroopHonorHelper {
data class Honor(
val id: Int,
val name: String,
val iconUrl: String,
val priority: Int
)
private val honorList = listOf(
Honor(1, "龙王", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150116_n4PxCiurbm.png", 1),
Honor(2, "群聊之火", "https://qzonestyle.gtimg.cn/aoi/sola/20200217190136_92JEGFKC5k.png", 3),
Honor(3, "群聊炽焰", "https://qzonestyle.gtimg.cn/aoi/sola/20200217190204_zgCTeSrMq1.png", 4),
Honor(5, "冒尖小春笋", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150335_tUJCAtoKVP.png", 5),
Honor(6, "快乐源泉", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150434_3tDmsJExCP.png", 7),
Honor(7, "学术新星", "https://sola.gtimg.cn/aoi/sola/20200515140645_j0X6gbuHNP.png", 8),
Honor(8, "顶尖学霸", "https://sola.gtimg.cn/aoi/sola/20200515140639_0CtWOpfVzK.png", 9),
Honor(9, "至尊学神", "https://sola.gtimg.cn/aoi/sola/20200515140628_P8UEYBjMBT.png", 10),
Honor(10, "一笔当先", "https://sola.gtimg.cn/aoi/sola/20200515140654_4r94tSCdaB.png", 11),
Honor(11, "奋进小翠竹", "https://sola.gtimg.cn/aoi/sola/20200812151819_wbj6z2NGoB.png", 6),
Honor(12, "氛围魔杖", "https://sola.gtimg.cn/aoi/sola/20200812151831_4ZJgQCaD1H.png", 2),
Honor(13, "壕礼皇冠", "https://sola.gtimg.cn/aoi/sola/20200930154050_juZOAMg7pt.png", 12)
)
fun decodeHonor(userId: Long, honorId: Int, honorFlag: Byte): GroupMemberHonor? {
val flag = calcHonorFlag(honorId, honorFlag)
val honor = if ((honorId != 1 && honorId != 2 && honorId != 3) || flag != 1) {
honorList.find { it.id == honorId }
} else {
val honor = honorList.find { it.id == honorId }
honor?.let {
val url = "https://static-res.qq.com/static-res/groupInteract/vas/a/${honorId}_1.png"
it.copy(iconUrl = url)
}
}
return honor?.let {
GroupMemberHonor(
userId,
"",
it.iconUrl,
0,
it.id,
it.name
)
}
}
private fun calcHonorFlag(honorId: Int, honorFlag: Byte): Int {
val flag = honorFlag.toInt()
if (flag == 0) {
return 0
}
return when {
honorId == 1 -> flag
honorId == 2 || honorId == 3 -> flag shr 2
honorId != 4 -> 0
else -> flag shr 4
} and 3
}
}

View File

@ -23,7 +23,7 @@ internal object BanTroopMember: IActionHandler() {
duration: Int = 30 * 60,
echo: JsonElement = EmptyJsonString
): String {
if (!GroupSvc.isAdmin(groupId.toString())) {
if (!GroupSvc.isAdmin(groupId)) {
return logic("You are not the administrator of the group.", echo)
}
GroupSvc.banMember(groupId, userId, duration)

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("create_group_file_folder")
internal object CreateGroupFileFolder: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val folderName = session.getString("name")
val echo = session.echo
return invoke(groupId, folderName, echo)
}
suspend operator fun invoke(groupId: String, folderName: String, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, folderName: String, echo: JsonElement = EmptyJsonString): String {
val result = FileSvc.createFileFolder(groupId, folderName)
if (result.isFailure) {
return ok(msg = result.exceptionOrNull()?.message ?: "无法创建群文件夹", echo = echo)

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("delete_group_file")
internal object DeleteGroupFile: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val fileId = session.getString("file_id")
val busid = session.getInt("busid")
return invoke(groupId, fileId, busid, session.echo)
}
suspend operator fun invoke(groupId: String, fileId: String, bizId: Int, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, fileId: String, bizId: Int, echo: JsonElement = EmptyJsonString): String {
if(!FileSvc.deleteGroupFile(groupId, bizId, fileId)) {
return error("删除失败", echo = echo)
}

View File

@ -10,12 +10,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("delete_group_folder")
internal object DeleteGroupFolder: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val folderId = session.getString("folder_id")
return invoke(groupId, folderId, session.echo)
}
suspend operator fun invoke(groupId: String, folderId: String, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, folderId: String, echo: JsonElement = EmptyJsonString): String {
if(!FileSvc.deleteGroupFolder(groupId, folderId)) {
return error(why = "删除群文件夹失败", echo = echo)
}

View File

@ -10,12 +10,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_file_system_info")
internal object GetGroupFileSystemInfo: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
return invoke(groupId, session.echo)
}
suspend operator fun invoke(groupId: String, echo: JsonElement = EmptyJsonString): String {
return ok(data = FileSvc.getGroupFileSystemInfo(groupId.toLong()), echo)
suspend operator fun invoke(groupId: Long, echo: JsonElement = EmptyJsonString): String {
return ok(data = FileSvc.getGroupFileSystemInfo(groupId), echo)
}
override val requiredParams: Array<String> = arrayOf("group_id")

View File

@ -10,14 +10,14 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_file_url")
internal object GetGroupFileUrl: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val fileId = session.getString("file_id")
val busid = session.getInt("busid")
return invoke(groupId, fileId, busid, session.echo)
}
suspend operator fun invoke(groupId: String, fileId: String, busid: Int, echo: JsonElement = EmptyJsonString): String {
return ok(data = FileSvc.getGroupFileInfo(groupId.toLong(), fileId, busid), echo = echo)
suspend operator fun invoke(groupId: Long, fileId: String, busid: Int, echo: JsonElement = EmptyJsonString): String {
return ok(data = FileSvc.getGroupFileInfo(groupId, fileId, busid), echo = echo)
}
override val requiredParams: Array<String> = arrayOf("group_id", "file_id", "busid")

View File

@ -8,7 +8,7 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_msg_history")
internal object GetGroupMsgHistory: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val cnt = session.getIntOrNull("count") ?: 20
val startId = session.getIntOrNull("message_seq")?.let {
if (it == 0) return@let 0L
@ -16,7 +16,7 @@ internal object GetGroupMsgHistory: IActionHandler() {
.messageMappingDao()
.queryByMsgHashId(it)?.qqMsgId
} ?: 0L
return GetHistoryMsg("group", groupId, cnt, startId, session.echo)
return GetHistoryMsg("group", groupId.toString(), cnt, startId, session.echo)
}
override val requiredParams: Array<String> = arrayOf("group_id")

View File

@ -10,12 +10,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_root_files")
internal object GetGroupRootFiles: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
return invoke(groupId, session.echo)
}
suspend operator fun invoke(groupId: String, echo: JsonElement = EmptyJsonString): String {
FileSvc.getGroupRootFiles(groupId.toLong()).onSuccess {
suspend operator fun invoke(groupId: Long, echo: JsonElement = EmptyJsonString): String {
FileSvc.getGroupRootFiles(groupId).onSuccess {
return ok(it, echo = echo)
}.getOrNull()
return error(why = "获取失败", echo = echo)

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_files_by_folder")
internal object GetGroupSubFiles: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val folderId = session.getString("folder_id")
return invoke(groupId, folderId, session.echo)
}
suspend operator fun invoke(groupId: String, folderId: String, echo: JsonElement = EmptyJsonString): String {
FileSvc.getGroupFiles(groupId.toLong(), folderId).onSuccess {
suspend operator fun invoke(groupId: Long, folderId: String, echo: JsonElement = EmptyJsonString): String {
FileSvc.getGroupFiles(groupId, folderId).onSuccess {
return ok(it, echo = echo)
}.getOrNull()
return error(why = "获取失败", echo = echo)

View File

@ -14,7 +14,7 @@ import moe.fuqiuluo.symbols.OneBotHandler
internal object GetGuildMemberProfile: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val guildId = session.getString("guild_id").toULong()
val userId = session.getString("user_id").toULong()
val userId = session.getLong("user_id").toULong()
return invoke(guildId, userId, session.echo)
}

View File

@ -25,7 +25,7 @@ import kotlin.coroutines.suspendCoroutine
internal object GetHistoryMsg : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val msgType = session.getString("message_type")
val peerId = session.getString(if (msgType == "group") "group_id" else "user_id")
val peerId = session.getLong(if (msgType == "group") "group_id" else "user_id").toString()
val cnt = session.getIntOrNull("count") ?: 20
val startId = session.getIntOrNull("message_seq")?.let {

View File

@ -10,12 +10,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_not_joined_group_info")
internal object GetNotJoinedGroupInfo: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
return invoke(groupId, session.echo)
}
suspend operator fun invoke(groupId: String, echo: JsonElement = EmptyJsonString): String {
GroupSvc.getNotJoinedGroupInfo(groupId = groupId.toLong()).onSuccess {
suspend operator fun invoke(groupId: Long, echo: JsonElement = EmptyJsonString): String {
GroupSvc.getNotJoinedGroupInfo(groupId = groupId).onSuccess {
return ok(it, echo = echo)
}.exceptionOrNull()?.let {
return error(it.message ?: "无法获取群信息", echo = echo)

View File

@ -15,7 +15,7 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_user_info", ["get_profile_card"])
internal object GetProfileCard: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val uin = session.getString("user_id")
val uin = session.getLong("user_id")
val refresh = session.getBooleanOrDefault("refresh", session.getBooleanOrDefault("no_cache", false))
var card: Card? = CardSvc.getProfileCard(uin).getOrNull()

View File

@ -14,11 +14,11 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_stranger_info", ["_get_stranger_info"])
internal object GetStrangerInfo: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val uid = session.getString("user_id")
return invoke(uid, session.echo)
val userId = session.getLong("user_id")
return invoke(userId, session.echo)
}
suspend operator fun invoke(userId: String, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(userId: Long, echo: JsonElement = EmptyJsonString): String {
val info = CardSvc.refreshAndGetProfileCard(userId).onFailure {
return logic("unable to fetch stranger info", echo)
}.getOrThrow()
@ -71,7 +71,7 @@ internal object GetStrangerInfo: IActionHandler() {
@Serializable
data class StrangerInfo(
@SerialName("user_id") val uid: String,
@SerialName("user_id") val uid: Long,
@SerialName("nickname") val nickname: String,
@SerialName("age") val age: Byte,
@SerialName("sex") val sex: String,

View File

@ -2,6 +2,7 @@ package moe.fuqiuluo.shamrock.remote.action.handlers
import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.shamrock.helper.TroopHonorHelper.decodeHonor
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.data.GroupAllHonor
@ -17,12 +18,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_honor_info", ["get_troop_honor_info"])
internal object GetTroopHonor: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val refresh = session.getBooleanOrDefault("refresh", session.getBooleanOrDefault("no_cache", false))
return invoke(groupId, refresh, session.echo)
}
suspend operator fun invoke(groupId: String, refresh: Boolean, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, refresh: Boolean, echo: JsonElement = EmptyJsonString): String {
val honorInfo = ArrayList<GroupMemberHonor>()
GroupSvc.getGroupMemberList(groupId, refresh).onFailure {
@ -30,7 +31,7 @@ internal object GetTroopHonor: IActionHandler() {
}.onSuccess { memberList ->
memberList.forEach { member ->
GroupSvc.parseHonor(member.honorList).forEach {
val honor = nativeDecodeHonor(member.memberuin, it, member.mHonorRichFlag)
val honor = decodeHonor(member.memberuin.toLong(), it, member.mHonorRichFlag)
if (honor != null) {
honor.nick = member.troopnick.ifEmpty { member.friendnick }
honorInfo.add(honor)
@ -40,7 +41,7 @@ internal object GetTroopHonor: IActionHandler() {
}
return ok(GroupAllHonor(
groupId = groupId.toLong(),
groupId = groupId,
currentTalkActive = honorInfo.firstOrNull {
it.id == HONOR_TALKATIVE
},
@ -54,6 +55,4 @@ internal object GetTroopHonor: IActionHandler() {
}
override val requiredParams: Array<String> = arrayOf("group_id")
private external fun nativeDecodeHonor(userId: String, honorId: Int, honorFlag: Byte): GroupMemberHonor?
}

View File

@ -11,12 +11,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_info")
internal object GetTroopInfo: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val refresh = session.getBooleanOrDefault("refresh", session.getBooleanOrDefault("no_cache", false))
return invoke(groupId, refresh, session.echo)
}
suspend operator fun invoke(groupId: String, refresh: Boolean, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, refresh: Boolean, echo: JsonElement = EmptyJsonString): String {
val groupInfo = GroupSvc.getGroupInfo(groupId, refresh).getOrNull()
return if ( groupInfo == null || groupInfo.troopuin.isNullOrBlank()) {
logic("Unable to obtain group information", echo)

View File

@ -30,7 +30,7 @@ internal object GetTroopList : IActionHandler() {
groupName = groupInfo.troopname ?: groupInfo.newTroopName
?: groupInfo.oldTroopName,
groupRemark = groupInfo.troopRemark,
adminList = GroupSvc.getAdminList(groupInfo.troopuin, true),
adminList = GroupSvc.getAdminList(groupInfo.troopuin.toLong(), true),
classText = groupInfo.mGroupClassExtText,
isFrozen = groupInfo.mIsFreezed != 0,
maxMember = groupInfo.wMemberMax,

View File

@ -6,7 +6,6 @@ import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.data.SimpleTroopMemberInfo
import moe.fuqiuluo.shamrock.remote.service.data.push.MemberRole
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
import moe.fuqiuluo.symbols.OneBotHandler
@ -14,20 +13,20 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_member_info")
internal object GetTroopMemberInfo : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val uin = session.getString("user_id")
val groupId = session.getString("group_id")
val userId = session.getLong("user_id")
val groupId = session.getLong("group_id")
val refresh = session.getBooleanOrDefault("refresh", session.getBooleanOrDefault("no_cache", false))
return invoke(groupId, uin, refresh, session.echo)
return invoke(groupId, userId, refresh, session.echo)
}
suspend operator fun invoke(
groupId: String,
uin: String,
groupId: Long,
userId: Long,
refresh: Boolean,
echo: JsonElement = EmptyJsonString
): String {
val info = GroupSvc.getTroopMemberInfoByUin(groupId, uin, refresh).onFailure {
val info = GroupSvc.getTroopMemberInfoByUin(groupId, userId, refresh).onFailure {
return error(it.message ?: "unknown error", echo)
}.getOrThrow()
@ -42,7 +41,7 @@ internal object GetTroopMemberInfo : IActionHandler() {
joinTime = info.join_time,
lastActiveTime = info.last_active_time,
uniqueName = info.mUniqueTitle,
groupId = groupId.toLong(),
groupId = groupId,
nick = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "",
sex = when (info.sex.toShort()) {
Card.FEMALE -> "female"
@ -52,7 +51,7 @@ internal object GetTroopMemberInfo : IActionHandler() {
area = info.alias ?: "",
lastSentTime = info.last_active_time,
level = info.level,
role = GroupSvc.getMemberRole(groupId.toLong(), uin.toLong()),
role = GroupSvc.getMemberRole(groupId, userId),
unfriendly = false,
title = info.mUniqueTitle ?: "",
titleExpireTime = info.mUniqueTitleExpire,

View File

@ -14,20 +14,20 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_member_list")
internal object GetTroopMemberList : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val refresh = session.getBooleanOrDefault("refresh", session.getBooleanOrDefault("no_cache", false))
return invoke(groupId, refresh, session.echo)
}
suspend operator fun invoke(
groupId: String,
groupId: Long,
refresh: Boolean,
echo: JsonElement = EmptyJsonString
): String {
val memberList = GroupSvc.getGroupMemberList(groupId, refresh).onFailure {
return error(it.message ?: "unknown error", echo, arrayResult = true)
}.getOrThrow()
val prohibitedMemberList = GroupSvc.getProhibitedMemberList(groupId.toLong())
val prohibitedMemberList = GroupSvc.getProhibitedMemberList(groupId)
.getOrDefault(arrayListOf())
.associate { it.memberUin to it.shutuptimestap.toLong() }
return ok(arrayListOf<SimpleTroopMemberInfo>().apply {
@ -44,7 +44,7 @@ internal object GetTroopMemberList : IActionHandler() {
joinTime = info.join_time,
lastActiveTime = info.last_active_time,
uniqueName = info.mUniqueTitle,
groupId = groupId.toLong(),
groupId = groupId,
nick = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "",
sex = when (info.sex.toShort()) {
Card.FEMALE -> "female"
@ -54,7 +54,7 @@ internal object GetTroopMemberList : IActionHandler() {
area = info.alias ?: "",
lastSentTime = info.last_active_time,
level = info.level,
role = GroupSvc.getMemberRole(groupId.toLong(), info.memberuin.toLong())
role = GroupSvc.getMemberRole(groupId, info.memberuin.toLong())
/*when {
GroupSvc.getOwner(groupId)
.toString() == info.memberuin -> MemberRole.Owner

View File

@ -10,12 +10,12 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("poke")
internal object GroupPoke: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val userId = session.getString("user_id")
val groupId = session.getLong("group_id")
val userId = session.getLong("user_id")
return invoke(groupId, userId, session.echo)
}
operator fun invoke(groupId: String, userId: String, echo: JsonElement = EmptyJsonString): String {
operator fun invoke(groupId: Long, userId: Long, echo: JsonElement = EmptyJsonString): String {
GroupSvc.poke(groupId, userId)
return ok("成功", echo)
}

View File

@ -16,15 +16,15 @@ import kotlin.coroutines.suspendCoroutine
@OneBotHandler("is_blacklist_uin")
internal object IsBlackListUin: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val userId = session.getString("user_id")
val userId = session.getLong("user_id")
return invoke(userId, session.echo)
}
suspend operator fun invoke(uin: String, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(uin: Long, echo: JsonElement = EmptyJsonString): String {
val blacklistApi = QRoute.api(IProfileCardBlacklistApi::class.java)
val isBlack = withTimeoutOrNull(5000) {
suspendCoroutine { continuation ->
blacklistApi.isBlackOrBlackedUin(uin) {
blacklistApi.isBlackOrBlackedUin(uin.toString()) {
continuation.resume(it)
}
}

View File

@ -10,15 +10,15 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("leave_group", ["set_group_leave"])
internal object LeaveTroop: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
return invoke(groupId, session.echo)
}
operator fun invoke(groupId: String, echo: JsonElement = EmptyJsonString): String {
operator fun invoke(groupId: Long, echo: JsonElement = EmptyJsonString): String {
if (GroupSvc.isOwner(groupId)) {
return error("you are the owner of this group", echo)
}
GroupSvc.resignTroop(groupId.toLong())
GroupSvc.resignTroop(groupId)
return ok("成功", echo)
}

View File

@ -11,17 +11,17 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("set_group_card")
internal object ModifyTroopMemberName: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val userId = session.getString("user_id")
val groupId = session.getLong("group_id")
val userId = session.getLong("user_id")
val name = session.getStringOrNull("card") ?: ""
return invoke(groupId, userId, name, session.echo)
}
operator fun invoke(groupId: String, userId: String, card: String, echo: JsonElement = EmptyJsonString): String {
if (!GroupSvc.isAdmin(groupId) && userId != TicketSvc.getUin()) {
operator fun invoke(groupId: Long, userId: Long, card: String, echo: JsonElement = EmptyJsonString): String {
if (!GroupSvc.isAdmin(groupId) && userId != TicketSvc.getUin().toLong()) {
return logic("you are not admin", echo)
}
return if(GroupSvc.modifyGroupMemberCard(groupId.toLong(), userId.toLong(), card))
return if(GroupSvc.modifyGroupMemberCard(groupId, userId, card))
ok("成功", echo)
else error("check if member or group exist", echo)
}

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("set_group_name")
internal object ModifyTroopName: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val groupName = session.getString("group_name")
return invoke(groupId, groupName, session.echo)
}
operator fun invoke(groupId: String, name: String, echo: JsonElement = EmptyJsonString): String {
operator fun invoke(groupId: Long, name: String, echo: JsonElement = EmptyJsonString): String {
return if (GroupSvc.isAdmin(groupId)) {
GroupSvc.modifyTroopName(groupId, name)
ok("成功", echo)

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("set_group_remark", ["modify_group_remark"])
internal object ModifyTroopRemark: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val remark = session.getStringOrNull("remark") ?: ""
return invoke(groupId, remark, session.echo)
}
operator fun invoke(groupId: String, remark: String, echo: JsonElement = EmptyJsonString): String {
return if(GroupSvc.modifyGroupRemark(groupId.toLong(), remark))
operator fun invoke(groupId: Long, remark: String, echo: JsonElement = EmptyJsonString): String {
return if(GroupSvc.modifyGroupRemark(groupId, remark))
ok("成功", echo)
else error("check if member or group exist", echo)
}

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("rename_group_folder")
internal object RenameGroupFolder: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val folderId = session.getString("folder_id")
val name = session.getString("name")
return invoke(groupId, folderId, name, session.echo)
}
suspend operator fun invoke(groupId: String, folderId: String, name: String, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, folderId: String, name: String, echo: JsonElement = EmptyJsonString): String {
if (!FileSvc.renameFolder(groupId, folderId, name)) {
return error("rename folder failed", echo = echo)
}

View File

@ -39,27 +39,27 @@ internal object SendForwardMessage : IActionHandler() {
}
}
val peerId = when (chatType) {
MsgConstant.KCHATTYPEGROUP -> session.getStringOrNull("group_id") ?: return noParam(
MsgConstant.KCHATTYPEGROUP -> session.getLongOrNull("group_id") ?: return noParam(
"group_id",
session.echo
)
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getStringOrNull("user_id")
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getLongOrNull("user_id")
?: return noParam("user_id", session.echo)
else -> error("unknown chat type: $chatType")
}
}.toString()
val fromId = when (chatType) {
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getStringOrNull("group_id")
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getLongOrNull("group_id")
?: return noParam("group_id", session.echo)
MsgConstant.KCHATTYPEC2C -> session.getStringOrNull("user_id") ?: return noParam(
MsgConstant.KCHATTYPEC2C -> session.getLongOrNull("user_id") ?: return noParam(
"user_id",
session.echo
)
else -> error("unknown chat type: $chatType")
}
}.toString()
return if (session.isArray("messages")) {
val messages = session.getArray("messages")
invoke(chatType, peerId, messages, fromId, echo = session.echo)

View File

@ -8,10 +8,10 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("send_group_forward_msg")
internal object SendGroupForwardMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
return if (session.isArray("messages")) {
val messages = session.getArray("messages")
SendForwardMessage(MsgConstant.KCHATTYPEGROUP, groupId, messages, echo = session.echo)
SendForwardMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), messages, echo = session.echo)
} else {
logic("未知格式合并转发消息", session.echo)
}

View File

@ -9,19 +9,19 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("send_group_message", ["send_group_msg"])
internal object SendGroupMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val retryCnt = session.getIntOrNull("retry_cnt")
val recallDuration = session.getLongOrNull("recall_duration")
return if (session.isString("message")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
val message = session.getString("message")
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, autoEscape, echo = session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, autoEscape, echo = session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
} else if (session.isObject("message")) {
val message = session.getObject("message")
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, listOf( message ).jsonArray, session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), listOf( message ).jsonArray, session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
} else {
val message = session.getArray("message")
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, session.echo, retryCnt = retryCnt ?: 3, recallDuration = recallDuration)
}
}

View File

@ -41,15 +41,15 @@ internal object SendMessage: IActionHandler() {
}
}
val peerId = when(chatType) {
MsgConstant.KCHATTYPEGROUP -> session.getStringOrNull("group_id") ?: return noParam("group_id", session.echo)
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getStringOrNull("user_id") ?: return noParam("user_id", session.echo)
MsgConstant.KCHATTYPEGROUP -> session.getLongOrNull("group_id") ?: return noParam("group_id", session.echo)
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getLongOrNull("user_id") ?: return noParam("user_id", session.echo)
else -> error("unknown chat type: $chatType")
}
}.toString()
val fromId = when(chatType) {
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getStringOrNull("group_id") ?: return noParam("group_id", session.echo)
MsgConstant.KCHATTYPEC2C -> session.getStringOrNull("user_id") ?: return noParam("user_id", session.echo)
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> session.getLongOrNull("group_id") ?: return noParam("group_id", session.echo)
MsgConstant.KCHATTYPEC2C -> session.getLongOrNull("user_id") ?: return noParam("user_id", session.echo)
else -> error("unknown chat type: $chatType")
}
}.toString()
val retryCnt = session.getIntOrNull("retry_cnt")
val recallDuration = session.getLongOrNull("recall_duration")
return if (session.isString("message")) {

View File

@ -8,10 +8,10 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("send_private_forward_msg")
internal object SendPrivateForwardMessage : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val userId = session.getString("user_id")
val userId = session.getLong("user_id")
return if (session.isArray("messages")) {
val messages = session.getArray("messages")
SendForwardMessage(MsgConstant.KCHATTYPEC2C, userId, messages, echo = session.echo)
SendForwardMessage(MsgConstant.KCHATTYPEC2C, userId.toString(), messages, echo = session.echo)
} else {
logic("未知格式合并转发消息", session.echo)
}

View File

@ -7,45 +7,33 @@ import moe.fuqiuluo.shamrock.tools.jsonArray
import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("send_private_msg", ["send_private_message"])
internal object SendPrivateMessage: IActionHandler() {
internal object SendPrivateMessage : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val userId = session.getString("user_id")
val groupId = session.getStringOrNull("group_id")
val userId = session.getLong("user_id")
val groupId = session.getLongOrNull("group_id")
val chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP
val retryCnt = session.getIntOrNull("retry_cnt")
val recallDuration = session.getLongOrNull("recall_duration")
return if (session.isString("message")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
val message = session.getString("message")
SendMessage.invoke(
SendMessage(
chatType = chatType,
peerId = userId,
peerId = userId.toString(),
message = message,
autoEscape = autoEscape,
echo = session.echo,
fromId = groupId ?: userId,
retryCnt = retryCnt ?: 3,
recallDuration = recallDuration
)
} else if (session.isArray("message")) {
val message = session.getArray("message")
SendMessage(
chatType = chatType,
peerId = userId,
message = message,
echo = session.echo,
fromId = groupId ?: userId,
fromId = groupId?.toString() ?: userId.toString(),
retryCnt = retryCnt ?: 3,
recallDuration = recallDuration
)
} else {
val message = session.getObject("message")
SendMessage(
chatType = chatType,
peerId = userId,
message = listOf( message ).jsonArray,
peerId = userId.toString(),
message = if (session.isArray("message")) session.getArray("message") else listOf(session.getObject("message")).jsonArray,
echo = session.echo,
fromId = groupId ?: userId,
fromId = groupId?.toString() ?: userId.toString(),
retryCnt = retryCnt ?: 3,
recallDuration = recallDuration
)

View File

@ -17,7 +17,7 @@ internal object SetGroupAdmin: IActionHandler() {
}
operator fun invoke(groupId: Long, userId: Long, enable: Boolean, echo: JsonElement = EmptyJsonString): String {
if (!GroupSvc.isOwner(groupId.toString())) {
if (!GroupSvc.isOwner(groupId)) {
return logic("you are not owner", echo)
}
GroupSvc.setGroupAdmin(groupId, userId, enable)

View File

@ -10,13 +10,13 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("set_group_special_title")
internal object SetGroupUnique: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val userId = session.getString("user_id")
val groupId = session.getLong("group_id")
val userId = session.getLong("user_id")
val unique = session.getString("special_title")
return invoke(groupId, userId, unique, session.echo)
}
suspend operator fun invoke(groupId: String, userId: String, unique: String, echo: JsonElement = EmptyJsonString): String {
suspend operator fun invoke(groupId: Long, userId: Long, unique: String, echo: JsonElement = EmptyJsonString): String {
if (!GroupSvc.isOwner(groupId)) {
return error("you are not owner", echo)
}

View File

@ -15,7 +15,7 @@ internal object SetGuildMemberRole: IActionHandler() {
val role = session.getString("role_id").toULong()
val set = session.getBooleanOrDefault("set", false)
return if (session.has("user_id")) {
val userId = session.getString("user_id").toULong()
val userId = session.getLong("user_id").toULong()
invoke(guildId, userId, role, set, echo = session.echo)
} else if (session.isArray("users")) {
invoke(guildId, session.getArray("users").map {

View File

@ -11,15 +11,15 @@ import mqq.app.MobileQQ
@OneBotHandler("switch_account")
internal object SwitchAccount: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val userId = session.getString("user_id")
val userId = session.getLong("user_id")
return invoke(userId, session.echo)
}
operator fun invoke(
userId: String,
userId: Long,
echo: JsonElement = EmptyJsonString
): String {
val account = MobileQQ.getMobileQQ().allAccounts.firstOrNull { it.uin == userId }
val account = MobileQQ.getMobileQQ().allAccounts.firstOrNull { it.uin == userId.toString() }
?: return error("账号不存在", echo)
val runtime = AppRuntimeFetcher.appRuntime
val result = kotlin.runCatching {

View File

@ -34,7 +34,7 @@ import kotlin.coroutines.resume
@OneBotHandler("upload_group_file")
internal object UploadGroupFile : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getString("group_id")
val groupId = session.getLong("group_id")
val file = session.getString("file")
val name = session.getString("name")
.replace("/", "_")
@ -46,7 +46,7 @@ internal object UploadGroupFile : IActionHandler() {
}
suspend operator fun invoke(
groupId: String,
groupId: Long,
file: String,
name: String,
echo: JsonElement = EmptyJsonString
@ -105,7 +105,7 @@ internal object UploadGroupFile : IActionHandler() {
val msgIdPair = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEGROUP)
val info = (withTimeoutOrNull((srcFile.length() / (125 * 1024)) * 1000 + 5000) {
val msgService = QRoute.api(IMsgService::class.java)
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId)
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId.toString())
suspendCancellableCoroutine<FileTransNotifyInfo?> {
msgService.sendMsgWithMsgId(
contact, msgIdPair.qqMsgId, arrayListOf(msgElement)

View File

@ -35,7 +35,7 @@ import kotlin.coroutines.resume
@OneBotHandler("upload_private_file")
internal object UploadPrivateFile : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val userId = session.getString("user_id")
val userId = session.getLong("user_id")
val file = session.getString("file")
val name = session.getString("name")
.replace("/", "_")
@ -47,7 +47,7 @@ internal object UploadPrivateFile : IActionHandler() {
}
suspend operator fun invoke(
userId: String,
userId: Long,
file: String,
name: String,
echo: JsonElement = EmptyJsonString
@ -106,7 +106,7 @@ internal object UploadPrivateFile : IActionHandler() {
val msgIdPair = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEC2C)
val info = (withTimeoutOrNull((srcFile.length() / (300 * 1024)) * 1000 + 5000) {
val msgService = QRoute.api(IMsgService::class.java)
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, userId)
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, userId.toString())
suspendCancellableCoroutine<FileTransNotifyInfo?> {
msgService.sendMsgWithMsgId(
contact, msgIdPair.qqMsgId, arrayListOf(msgElement)

View File

@ -18,8 +18,8 @@ import moe.fuqiuluo.shamrock.tools.getOrPost
fun Routing.friendAction() {
getOrPost("/get_stranger_info") {
val uin = fetchOrThrow("user_id")
call.respondText(GetStrangerInfo(uin), ContentType.Application.Json)
val userId = fetchOrThrow("user_id").toLong()
call.respondText(GetStrangerInfo(userId), ContentType.Application.Json)
}
getOrPost("/get_friend_list") {
@ -29,8 +29,8 @@ fun Routing.friendAction() {
}
getOrPost("/is_blacklist_uin") {
val uin = fetchOrThrow("user_id")
call.respondText(IsBlackListUin(uin), ContentType.Application.Json)
val userId = fetchOrThrow("user_id").toLong()
call.respondText(IsBlackListUin(userId), ContentType.Application.Json)
}
getOrPost("/get_friend_system_msg") {

View File

@ -26,7 +26,7 @@ fun Routing.troopAction() {
}
getOrPost("/get_not_joined_group_info") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
call.respondText(GetNotJoinedGroupInfo(groupId), ContentType.Application.Json)
}
@ -36,28 +36,28 @@ fun Routing.troopAction() {
}
getOrPost("/group_touch") {
val groupId = fetchOrThrow("group_id")
val userId = fetchOrThrow("user_id")
val groupId = fetchOrThrow("group_id").toLong()
val userId = fetchOrThrow("user_id").toLong()
call.respondText(GroupPoke(groupId, userId), ContentType.Application.Json)
}
getOrPost("/get_group_honor_info") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val refresh = fetchOrNull("no_cache")?.toBooleanStrict()
?: fetchOrNull("refresh")?.toBooleanStrict() ?: false
call.respondText(GetTroopHonor(groupId, refresh), ContentType.Application.Json)
}
getOrPost("/get_group_member_list") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val refresh = fetchOrNull("no_cache")?.toBooleanStrict()
?: fetchOrNull("refresh")?.toBooleanStrict() ?: false
call.respondText(GetTroopMemberList(groupId, refresh), ContentType.Application.Json)
}
getOrPost("/get_group_member_info") {
val groupId = fetchOrThrow("group_id")
val userId = fetchOrThrow("user_id")
val groupId = fetchOrThrow("group_id").toLong()
val userId = fetchOrThrow("user_id").toLong()
val refresh = fetchOrNull("no_cache")?.toBooleanStrict()
?: fetchOrNull("refresh")?.toBooleanStrict() ?: false
call.respondText(GetTroopMemberInfo(groupId, userId, refresh), ContentType.Application.Json)
@ -70,48 +70,48 @@ fun Routing.troopAction() {
}
getOrPost("/get_group_info") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val refresh = fetchOrNull("no_cache")?.toBooleanStrict()
?: fetchOrNull("refresh")?.toBooleanStrict() ?: false
call.respondText(GetTroopInfo(groupId, refresh), ContentType.Application.Json)
}
getOrPost("/set_group_special_title") {
val groupId = fetchOrThrow("group_id")
val userId = fetchOrThrow("user_id")
val groupId = fetchOrThrow("group_id").toLong()
val userId = fetchOrThrow("user_id").toLong()
val title = fetchOrThrow("special_title")
call.respondText(SetGroupUnique(groupId, userId, title), ContentType.Application.Json)
}
getOrPost("/set_group_name") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val card = fetchOrThrow("group_name")
call.respondText(ModifyTroopName(groupId, card), ContentType.Application.Json)
}
getOrPost("/set_group_card") {
val groupId = fetchOrThrow("group_id")
val userId = fetchOrThrow("user_id")
val groupId = fetchOrThrow("group_id").toLong()
val userId = fetchOrThrow("user_id").toLong()
val card = fetchOrNull("card") ?: ""
call.respondText(ModifyTroopMemberName(groupId, userId, card), ContentType.Application.Json)
}
getOrPost("/set_group_admin") {
val groupId = fetchOrThrow("group_id") .toLong()
val userId = fetchOrThrow("user_id") .toLong()
val groupId = fetchOrThrow("group_id").toLong()
val userId = fetchOrThrow("user_id").toLong()
val enable = fetchOrThrow("enable").toBooleanStrict()
call.respondText(SetGroupAdmin(groupId, userId, enable), ContentType.Application.Json)
}
getOrPost("/set_group_whole_ban") {
val groupId = fetchOrThrow("group_id") .toLong()
val groupId = fetchOrThrow("group_id").toLong()
val enable = fetchOrThrow("enable").toBooleanStrict()
call.respondText(SetGroupWholeBan(groupId, enable), ContentType.Application.Json)
}
getOrPost("/set_group_ban") {
val groupId = fetchOrThrow("group_id") .toLong()
val userId = fetchOrThrow("user_id") .toLong()
val groupId = fetchOrThrow("group_id").toLong()
val userId = fetchOrThrow("user_id").toLong()
val duration = fetchOrNull("duration")?.toInt() ?: (30 * 60)
call.respondText(BanTroopMember(groupId, userId, duration), ContentType.Application.Json)

View File

@ -48,7 +48,10 @@ fun Routing.messageAction() {
post {
val groupId = fetchPostOrNull("group_id")
val messages = fetchPostJsonArray("messages")
call.respondText(SendForwardMessage(MsgConstant.KCHATTYPEGROUP, groupId ?: "", messages), ContentType.Application.Json)
call.respondText(
SendForwardMessage(MsgConstant.KCHATTYPEGROUP, groupId ?: "", messages),
ContentType.Application.Json
)
}
get {
respond(false, Status.InternalHandlerError, "Not support GET method")
@ -59,7 +62,10 @@ fun Routing.messageAction() {
post {
val userId = fetchPostOrNull("user_id")
val messages = fetchPostJsonArray("messages")
call.respondText(SendForwardMessage(MsgConstant.KCHATTYPEC2C, userId ?: "", messages), ContentType.Application.Json)
call.respondText(
SendForwardMessage(MsgConstant.KCHATTYPEC2C, userId ?: "", messages),
ContentType.Application.Json
)
}
get {
respond(false, Status.InternalHandlerError, "Not support GET method")
@ -71,7 +77,10 @@ fun Routing.messageAction() {
val userId = fetchPostOrNull("user_id")
val groupId = fetchPostOrNull("group_id")
val messages = fetchPostJsonArray("messages")
call.respondText(SendForwardMessage(MsgConstant.KCHATTYPEC2C, userId ?: groupId?: "", messages), ContentType.Application.Json)
call.respondText(
SendForwardMessage(MsgConstant.KCHATTYPEC2C, userId ?: groupId ?: "", messages),
ContentType.Application.Json
)
}
get {
respond(false, Status.InternalHandlerError, "Not support GET method")
@ -137,15 +146,17 @@ fun Routing.messageAction() {
val recallDuration = fetchGetOrNull("recall_duration")?.toLongOrNull()
call.respondText(SendMessage(
chatType = chatType,
peerId = if (chatType == MsgConstant.KCHATTYPEC2C) userId!! else groupId!!,
message = message,
autoEscape = autoEscape,
fromId = groupId ?: userId ?: "",
retryCnt = retryCnt,
recallDuration = recallDuration
), ContentType.Application.Json)
call.respondText(
SendMessage(
chatType = chatType,
peerId = if (chatType == MsgConstant.KCHATTYPEC2C) userId!! else groupId!!,
message = message,
autoEscape = autoEscape,
fromId = groupId ?: userId ?: "",
retryCnt = retryCnt,
recallDuration = recallDuration
), ContentType.Application.Json
)
}
post {
val msgType = fetchPostOrThrow("message_type")
@ -157,39 +168,30 @@ fun Routing.messageAction() {
val peerId = if (chatType == MsgConstant.KCHATTYPEC2C) userId!! else groupId!!
val recallDuration = fetchPostOrNull("recall_duration")?.toLongOrNull()
call.respondText(if (isJsonData() && !isJsonString("message")) {
if (isJsonObject("message")) {
call.respondText(
if (isJsonData() && !isJsonString("message")) {
SendMessage(
chatType = chatType,
peerId = peerId,
message = listOf(fetchPostJsonObject("message")).jsonArray,
message = if (isJsonObject("message")) listOf(fetchPostJsonObject("message")).jsonArray else fetchPostJsonArray("message"),
fromId = groupId ?: userId ?: "",
retryCnt = retryCnt,
recallDuration = recallDuration
)
} else {
val autoEscape = fetchPostOrNull("auto_escape")?.toBooleanStrict() ?: false
//SendMessage(chatType, peerId, fetchPostOrThrow("message"), autoEscape)
SendMessage(
chatType = chatType,
peerId = peerId,
message = fetchPostJsonArray("message"),
message = fetchPostOrThrow("message"),
autoEscape = autoEscape,
fromId = groupId ?: userId ?: "",
retryCnt = retryCnt,
recallDuration = recallDuration
)
}
} else {
val autoEscape = fetchPostOrNull("auto_escape")?.toBooleanStrict() ?: false
//SendMessage(chatType, peerId, fetchPostOrThrow("message"), autoEscape)
SendMessage(
chatType = chatType,
peerId = peerId,
message = fetchPostOrThrow("message"),
autoEscape = autoEscape,
fromId = groupId ?: userId ?: "",
retryCnt = retryCnt,
recallDuration = recallDuration
)
}, ContentType.Application.Json)
}, ContentType.Application.Json
)
}
}
@ -201,7 +203,16 @@ fun Routing.messageAction() {
val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false
val recallDuration = fetchGetOrNull("recall_duration")?.toLongOrNull()
call.respondText(SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, autoEscape, retryCnt = retryCnt, recallDuration = recallDuration), ContentType.Application.Json)
call.respondText(
SendMessage(
MsgConstant.KCHATTYPEGROUP,
groupId,
message,
autoEscape,
retryCnt = retryCnt,
recallDuration = recallDuration
), ContentType.Application.Json
)
}
post {
val groupId = fetchPostOrThrow("group_id")
@ -212,28 +223,32 @@ fun Routing.messageAction() {
val result = if (isJsonData()) {
if (isJsonString("message")) {
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, fetchPostJsonString("message"), autoEscape, retryCnt = retryCnt, recallDuration = recallDuration)
SendMessage(
MsgConstant.KCHATTYPEGROUP,
groupId,
fetchPostJsonString("message"),
autoEscape,
retryCnt = retryCnt,
recallDuration = recallDuration
)
} else {
if (isJsonObject("message")) {
SendMessage(
chatType = MsgConstant.KCHATTYPEGROUP,
peerId = groupId,
message = listOf(fetchPostJsonObject("message")).jsonArray,
retryCnt = retryCnt,
recallDuration = recallDuration
)
} else {
SendMessage(
chatType = MsgConstant.KCHATTYPEGROUP,
peerId = groupId,
message = fetchPostJsonArray("message"),
retryCnt = retryCnt,
recallDuration = recallDuration
)
}
SendMessage(
chatType = MsgConstant.KCHATTYPEGROUP,
peerId = groupId,
message = if (isJsonObject("message")) listOf(fetchPostJsonObject("message")).jsonArray else fetchPostJsonArray("message"),
retryCnt = retryCnt,
recallDuration = recallDuration
)
}
} else {
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, fetchPostOrThrow("message"), autoEscape, retryCnt = retryCnt, recallDuration = recallDuration)
SendMessage(
MsgConstant.KCHATTYPEGROUP,
groupId,
fetchPostOrThrow("message"),
autoEscape,
retryCnt = retryCnt,
recallDuration = recallDuration
)
}
call.respondText(result, ContentType.Application.Json)
@ -248,14 +263,16 @@ fun Routing.messageAction() {
val retryCnt = fetchGetOrNull("retry_cnt")?.toInt() ?: 3
val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false
val recallDuration = fetchGetOrNull("recall_duration")?.toLongOrNull()
call.respondText(SendMessage(
chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP,
peerId = userId,
message = message,
autoEscape = autoEscape,
fromId = groupId ?: userId,
retryCnt = retryCnt, recallDuration = recallDuration
), ContentType.Application.Json)
call.respondText(
SendMessage(
chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP,
peerId = userId,
message = message,
autoEscape = autoEscape,
fromId = groupId ?: userId,
retryCnt = retryCnt, recallDuration = recallDuration
), ContentType.Application.Json
)
}
post {
val userId = fetchPostOrThrow("user_id")
@ -278,23 +295,14 @@ fun Routing.messageAction() {
retryCnt = retryCnt, recallDuration = recallDuration
)
} else {
if (isJsonObject("message")) {
SendMessage(
chatType = chatType,
peerId = userId,
message = listOf(fetchPostJsonObject("message")).jsonArray,
fromId = fromId,
retryCnt = retryCnt, recallDuration = recallDuration
)
} else {
SendMessage(
chatType = chatType,
peerId = userId,
message = fetchPostJsonArray("message"),
fromId = fromId,
retryCnt = retryCnt, recallDuration = recallDuration
)
}
SendMessage(
chatType = chatType,
peerId = userId,
message = if (isJsonObject("message")) listOf(fetchPostJsonObject("message")).jsonArray else fetchPostJsonArray("message"),
fromId = groupId ?: userId ?: "",
retryCnt = retryCnt,
recallDuration = recallDuration
)
}
} else {
SendMessage(

View File

@ -32,56 +32,56 @@ fun Routing.fetchRes() {
}
getOrPost("/upload_group_file") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val file = fetchOrThrow("file")
val name = fetchOrThrow("name")
call.respondText(UploadGroupFile(groupId, file, name), ContentType.Application.Json)
}
getOrPost("/upload_private_file") {
val userId = fetchOrThrow("user_id")
val userId = fetchOrThrow("user_id").toLong()
val file = fetchOrThrow("file")
val name = fetchOrThrow("name")
call.respondText(UploadPrivateFile(userId, file, name), ContentType.Application.Json)
}
getOrPost("/create_group_file_folder") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val name = fetchOrThrow("name")
call.respondText(CreateGroupFileFolder(groupId, name), ContentType.Application.Json)
}
getOrPost("/delete_group_folder") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val id = fetchOrThrow("folder_id")
call.respondText(DeleteGroupFolder(groupId, id), ContentType.Application.Json)
}
getOrPost("/delete_group_file") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val id = fetchOrThrow("file_id")
val busid = fetchOrThrow("busid").toInt()
call.respondText(DeleteGroupFile(groupId, id, busid), ContentType.Application.Json)
}
getOrPost("/get_group_file_system_info") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
call.respondText(GetGroupFileSystemInfo(groupId), ContentType.Application.Json)
}
getOrPost("/get_group_root_files") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
call.respondText(GetGroupRootFiles(groupId), ContentType.Application.Json)
}
getOrPost("/get_group_files_by_folder") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val folderId = fetchOrThrow("folder_id")
call.respondText(GetGroupSubFiles(groupId, folderId), ContentType.Application.Json)
}
getOrPost("/get_group_file_url") {
val groupId = fetchOrThrow("group_id")
val groupId = fetchOrThrow("group_id").toLong()
val id = fetchOrThrow("file_id")
val busid = fetchOrThrow("busid").toInt()
call.respondText(GetGroupFileUrl(groupId, id, busid), ContentType.Application.Json)

View File

@ -13,13 +13,13 @@ import moe.fuqiuluo.shamrock.utils.PlatformUtils
fun Routing.userAction() {
getOrPost("/switch_account") {
val userId = fetchOrThrow("user_id")
val userId = fetchOrThrow("user_id").toLong()
call.respondText(SwitchAccount(userId), ContentType.Application.Json)
}
getOrPost("/set_group_leave") {
val group = fetchOrThrow("group_id")
call.respondText(LeaveTroop(group), ContentType.Application.Json)
val groupId = fetchOrThrow("group_id").toLong()
call.respondText(LeaveTroop(groupId), ContentType.Application.Json)
}
getOrPost("/_get_online_clients") {

View File

@ -119,7 +119,7 @@ internal object GlobalEventTransmitter: BaseSvc() {
val botUin = app.longAccountUin
var nickName = record.sendNickName
if (nickName.isNullOrEmpty()) {
CardSvc.getProfileCard(record.senderUin.toString()).onSuccess {
CardSvc.getProfileCard(record.senderUin).onSuccess {
nickName = it.strNick ?: record.peerName
}
}
@ -167,7 +167,7 @@ internal object GlobalEventTransmitter: BaseSvc() {
val botUin = app.longAccountUin
var nickName = record.sendNickName
if (nickName.isNullOrEmpty()) {
CardSvc.getProfileCard(record.senderUin.toString()).onSuccess {
CardSvc.getProfileCard(record.senderUin).onSuccess {
nickName = it.strNick ?: record.peerName
}
}

View File

@ -77,6 +77,7 @@ internal object ShamrockConfig {
putBoolean("shell", intent.getBooleanExtra("shell", false)) // 开启Shell接口
putBoolean("enable_sync_msg_as_sent_msg", intent.getBooleanExtra("enable_sync_msg_as_sent_msg", false)) // 推送同步消息
putBoolean("forbid_useless_process", intent.getBooleanExtra("forbid_useless_process", false)) // 禁用QQ生成无用进程
putBoolean("enable_old_bdh", intent.getBooleanExtra("enable_old_bdh", false)) // 启用旧版BDH
}
Config.defaultToken = intent.getStringExtra("token")
Config.antiTrace = intent.getBooleanExtra("anti_qq_trace", true)
@ -175,6 +176,10 @@ internal object ShamrockConfig {
return mmkv.getBoolean("inject_packet", false)
}
fun enableOldBDH(): Boolean {
return mmkv.getBoolean("enable_old_bdh", false)
}
fun isDebug(): Boolean {
return mmkv.getBoolean("debug", false)
}

View File

@ -17,23 +17,14 @@ internal const val HONOR_ATMOSPHERE = 12
internal const val HONOR_GIFT = 13
@Serializable
internal data class GroupMemberHonor(
data class GroupMemberHonor(
@SerialName("user_id") val userId: Long,
@SerialName("nickname") var nick: String,
@SerialName("avatar") val avatar: String,
@SerialName("day_count") val dayCount: Int,
@SerialName("id") val id: Int,
@SerialName("description") val desc: String,
) {
constructor(userId: String, nick: String, avatar: String, dayCount: Int, id: Int, desc: String) : this(
userId.toLong(),
nick,
avatar,
dayCount,
id,
desc,
)
}
)
@Serializable
internal data class GroupAllHonor(
@ -45,4 +36,4 @@ internal data class GroupAllHonor(
@SerialName("strong_newbie_list") val strongNewbieList: List<GroupMemberHonor>?,
@SerialName("emotion_list") val emotionList: List<GroupMemberHonor>?,
@SerialName("all") val all: List<GroupMemberHonor>?,
)
)

View File

@ -384,7 +384,7 @@ internal object PrimitiveListener {
val targetUid = event.memberUid
val type = event.type
GroupSvc.getGroupMemberList(groupCode.toString(), true).onFailure {
GroupSvc.getGroupMemberList(groupCode, true).onFailure {
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
}.onSuccess {
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
@ -422,7 +422,7 @@ internal object PrimitiveListener {
val type = event.type
val operatorUid = event.operatorUid
GroupSvc.getGroupMemberList(groupCode.toString(), true).onFailure {
GroupSvc.getGroupMemberList(groupCode, true).onFailure {
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
}.onSuccess {
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)

View File

@ -46,16 +46,14 @@ val Collection<Any>.json: JsonArray
get() {
val arrayList = arrayListOf<JsonElement>()
forEach {
if (it != null) {
when (it) {
is JsonElement -> arrayList.add(it)
is Number -> arrayList.add(it.json)
is String -> arrayList.add(it.json)
is Boolean -> arrayList.add(it.json)
is Map<*, *> -> arrayList.add((it as Map<String, Any>).json)
is Collection<*> -> arrayList.add((it as Collection<Any>).json)
else -> error("unknown array type: ${it::class.java}")
}
when (it) {
is JsonElement -> arrayList.add(it)
is Number -> arrayList.add(it.json)
is String -> arrayList.add(it.json)
is Boolean -> arrayList.add(it.json)
is Map<*, *> -> arrayList.add((it as Map<String, Any>).json)
is Collection<*> -> arrayList.add((it as Collection<Any>).json)
else -> error("unknown array type: ${it::class.java}")
}
}
return arrayList.jsonArray

View File

@ -117,6 +117,9 @@ internal class HookWrapperCodec: IAction {
//from.serviceCmd = "ShamrockInjectedCmd_${from.serviceCmd}"
from.setBusinessFail(1)
from.putWupBuffer(EMPTY_BYTE_ARRAY)
} else if (from.serviceCmd.startsWith("trpc.o3.") && ShamrockConfig.isInjectPacket()) {
from.setBusinessFail(1)
from.putWupBuffer(EMPTY_BYTE_ARRAY)
} else {
pushOnReceive(from)
}