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)
|
||||
.addService(Authentication)
|
||||
.addService(ContactService)
|
||||
.addService(KritorService)
|
||||
.build()!!
|
||||
|
||||
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,
|
||||
headers: Map<String, String> = mapOf()
|
||||
): 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 connection = withContext(Dispatchers.IO) { url.openConnection() } as HttpURLConnection
|
||||
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