mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: 实现Kritor核心服务
Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
parent
c16f9d543c
commit
cb4268edef
@ -20,6 +20,7 @@ class KritorServer(
|
|||||||
.intercept(AuthInterceptor)
|
.intercept(AuthInterceptor)
|
||||||
.addService(Authentication)
|
.addService(Authentication)
|
||||||
.addService(ContactService)
|
.addService(ContactService)
|
||||||
|
.addService(KritorService)
|
||||||
.build()!!
|
.build()!!
|
||||||
|
|
||||||
fun start(block: Boolean = false) {
|
fun start(block: Boolean = false) {
|
||||||
|
118
xposed/src/main/java/kritor/service/KritorService.kt
Normal file
118
xposed/src/main/java/kritor/service/KritorService.kt
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package kritor.service
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
|
import com.tencent.mobileqq.app.QQAppInterface
|
||||||
|
import io.grpc.Status
|
||||||
|
import io.grpc.StatusRuntimeException
|
||||||
|
import io.kritor.core.ClearCacheRequest
|
||||||
|
import io.kritor.core.ClearCacheResponse
|
||||||
|
import io.kritor.core.DownloadFileRequest
|
||||||
|
import io.kritor.core.DownloadFileResponse
|
||||||
|
import io.kritor.core.GetCurrentAccountRequest
|
||||||
|
import io.kritor.core.GetCurrentAccountResponse
|
||||||
|
import io.kritor.core.GetVersionRequest
|
||||||
|
import io.kritor.core.GetVersionResponse
|
||||||
|
import io.kritor.core.KritorServiceGrpcKt
|
||||||
|
import io.kritor.core.SwitchAccountRequest
|
||||||
|
import io.kritor.core.SwitchAccountResponse
|
||||||
|
import io.kritor.core.clearCacheResponse
|
||||||
|
import io.kritor.core.downloadFileResponse
|
||||||
|
import io.kritor.core.getCurrentAccountResponse
|
||||||
|
import io.kritor.core.getVersionResponse
|
||||||
|
import io.kritor.core.switchAccountResponse
|
||||||
|
import moe.fuqiuluo.shamrock.tools.ShamrockVersion
|
||||||
|
import moe.fuqiuluo.shamrock.utils.DownloadUtils
|
||||||
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
|
import moe.fuqiuluo.shamrock.utils.MD5
|
||||||
|
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
||||||
|
import mqq.app.MobileQQ
|
||||||
|
import qq.service.QQInterfaces
|
||||||
|
import qq.service.QQInterfaces.Companion.app
|
||||||
|
import qq.service.contact.ContactHelper
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object KritorService: KritorServiceGrpcKt.KritorServiceCoroutineImplBase() {
|
||||||
|
@Grpc("KritorService", "GetVersion")
|
||||||
|
override suspend fun getVersion(request: GetVersionRequest): GetVersionResponse {
|
||||||
|
return getVersionResponse {
|
||||||
|
this.version = ShamrockVersion
|
||||||
|
this.appName = "Shamrock"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("KritorService", "ClearCache")
|
||||||
|
override suspend fun clearCache(request: ClearCacheRequest): ClearCacheResponse {
|
||||||
|
FileUtils.clearCache()
|
||||||
|
MMKVFetcher.mmkvWithId("audio2silk")
|
||||||
|
.clear()
|
||||||
|
return clearCacheResponse {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("KritorService", "GetCurrentAccount")
|
||||||
|
override suspend fun getCurrentAccount(request: GetCurrentAccountRequest): GetCurrentAccountResponse {
|
||||||
|
return getCurrentAccountResponse {
|
||||||
|
this.accountName = if (app is QQAppInterface) app.currentNickname else "unknown"
|
||||||
|
this.accountUid = app.currentUid ?: ""
|
||||||
|
this.accountUin = (app.currentUin ?: "0").toLong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("KritorService", "DownloadFile")
|
||||||
|
override suspend fun downloadFile(request: DownloadFileRequest): DownloadFileResponse {
|
||||||
|
val headerMap = mutableMapOf(
|
||||||
|
"User-Agent" to "Shamrock"
|
||||||
|
)
|
||||||
|
if (request.hasHeaders()) {
|
||||||
|
request.headers.split("[\r\n]").forEach {
|
||||||
|
val pair = it.split("=")
|
||||||
|
if (pair.size >= 2) {
|
||||||
|
val (k, v) = pair
|
||||||
|
headerMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp = FileUtils.getTmpFile("cache")
|
||||||
|
if (request.hasBase64()) {
|
||||||
|
val bytes = Base64.decode(request.base64, Base64.DEFAULT)
|
||||||
|
tmp.writeBytes(bytes)
|
||||||
|
} else if(request.hasUrl()) {
|
||||||
|
if(!DownloadUtils.download(
|
||||||
|
urlAdr = request.url,
|
||||||
|
dest = tmp,
|
||||||
|
headers = headerMap,
|
||||||
|
threadCount = if (request.hasThreadCnt()) request.threadCnt else 3
|
||||||
|
)) {
|
||||||
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("download failed"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp = if (!request.hasFileName()) FileUtils.renameByMd5(tmp)
|
||||||
|
else tmp.parentFile!!.resolve(request.fileName).also {
|
||||||
|
tmp.renameTo(it)
|
||||||
|
}
|
||||||
|
if (request.hasRootPath()) {
|
||||||
|
tmp = File(request.rootPath).resolve(tmp.name).also {
|
||||||
|
tmp.renameTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return downloadFileResponse {
|
||||||
|
this.fileMd5 = MD5.genFileMd5Hex(tmp.absolutePath)
|
||||||
|
this.fileAbsolutePath = tmp.absolutePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("KritorService", "SwitchAccount")
|
||||||
|
override suspend fun switchAccount(request: SwitchAccountRequest): SwitchAccountResponse {
|
||||||
|
val uin = if (request.hasAccountUin()) request.accountUin.toString()
|
||||||
|
else ContactHelper.getUinByUidAsync(request.accountUid)
|
||||||
|
val account = MobileQQ.getMobileQQ().allAccounts.firstOrNull { it.uin == uin }
|
||||||
|
?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("account not found"))
|
||||||
|
runCatching {
|
||||||
|
app.switchAccount(account, null)
|
||||||
|
}.onFailure {
|
||||||
|
throw StatusRuntimeException(Status.INTERNAL.withCause(it).withDescription("failed to switch account"))
|
||||||
|
}
|
||||||
|
return switchAccountResponse { }
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ object DownloadUtils {
|
|||||||
threadCount: Int = MAX_THREAD,
|
threadCount: Int = MAX_THREAD,
|
||||||
headers: Map<String, String> = mapOf()
|
headers: Map<String, String> = mapOf()
|
||||||
): Boolean {
|
): Boolean {
|
||||||
var threadCnt = if(threadCount == 0) MAX_THREAD else threadCount
|
var threadCnt = if(threadCount == 0 || threadCount < 0) MAX_THREAD else threadCount
|
||||||
val url = URL(urlAdr)
|
val url = URL(urlAdr)
|
||||||
val connection = withContext(Dispatchers.IO) { url.openConnection() } as HttpURLConnection
|
val connection = withContext(Dispatchers.IO) { url.openConnection() } as HttpURLConnection
|
||||||
headers.forEach { (k, v) ->
|
headers.forEach { (k, v) ->
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
package qq.service.contact
|
|
||||||
|
|
||||||
const val CMD_GET_PROFILE_DETAIL = "OidbSvc.0x480_9_IMCore"
|
|
||||||
const val CMD_SET_PROFILE_DETAIL = "OidbSvc.0x4ff_9_IMCore"
|
|
||||||
const val KET_INTERESTS = "interests"
|
|
||||||
const val KEY_AGE = "age"
|
|
||||||
const val KEY_BIRTHDAY = "birthday"
|
|
||||||
const val KEY_COLLEGE = "college"
|
|
||||||
const val KEY_COMPANY = "company"
|
|
||||||
const val KEY_CONSTELLATION = "key_constellation"
|
|
||||||
const val KEY_EMAIL = "email"
|
|
||||||
const val KEY_HOMETOWN = "hometown"
|
|
||||||
const val KEY_HOMETOWN_DESC = "hometown_desc"
|
|
||||||
const val KEY_LOCATION = "location"
|
|
||||||
const val KEY_LOCATION_DESC = "location_desc"
|
|
||||||
const val KEY_LOCATION_NAME = "location_name"
|
|
||||||
const val KEY_NICK = "nick"
|
|
||||||
const val KEY_PARSE_PROFILE_LOCATION = "parse_profile_location"
|
|
||||||
const val KEY_PERSONAL_NOTE = "personalNote"
|
|
||||||
const val KEY_PROFESSION = "profession"
|
|
||||||
const val KEY_SEX = "sex"
|
|
||||||
const val PARAM_ADD_FRIEND_SOURCE = "addFriendSource"
|
|
||||||
const val PARAM_COME_FROM_TYPE = "comeFromType"
|
|
||||||
const val PARAM_GET_CONTROL = "getControl"
|
|
||||||
const val PARAM_IS_FRIEND = "isFriend"
|
|
||||||
const val PARAM_LOGIN_SIG = "loginSig"
|
|
||||||
const val PARAM_QZONE_FEED_TIMESTAMP = "qZoneFeedTimeStamp"
|
|
||||||
const val PARAM_QZONE_SEED = "qZoneSeed"
|
|
||||||
const val PARAM_REQ_0X5EB = "req0x5ebList"
|
|
||||||
const val PARAM_REQ_EXTEND = "reqExtendFriend"
|
|
||||||
const val PARAM_REQ_MEDAL = "reqMedalWall"
|
|
||||||
const val PARAM_REQ_SERVICES = "reqServiceList"
|
|
||||||
const val PARAM_REQ_TEMPLATE = "reqTemplate"
|
|
||||||
const val PARAM_SEARCH_NAME = "searchName"
|
|
||||||
const val PARAM_SECURE_SIG = "secureSig"
|
|
||||||
const val PARAM_SELF_UIN = "selfUin"
|
|
||||||
const val PARAM_TARGET_UIN = "targetUin"
|
|
||||||
const val PARAM_TROOP_CODE = "troopCode"
|
|
||||||
const val PARAM_TROOP_UIN = "troopUin"
|
|
Loading…
x
Reference in New Issue
Block a user