mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-05 16:50:33 +08:00
Merge remote-tracking branch 'origin/master'
# Conflicts: # mirai-console/src/main/kotlin/net/mamoe/mirai/console/center/PluginCenter.kt
This commit is contained in:
commit
c1c114ef07
48
.github/workflows/cui.yml
vendored
Normal file
48
.github/workflows/cui.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: CuiCloud Publish
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Gradle clean
|
||||
run: ./gradlew clean
|
||||
- name: Gradle build
|
||||
run: ./gradlew build # if test's failed, don't publish
|
||||
- name: Gradle :mirai-console:cuiCloudUpload
|
||||
run: ./gradlew :mirai-console:cuiCloudUpload -Dcui_cloud_key=${{ secrets.CUI_CLOUD_KEY }} -Pcui_cloud_key=${{ secrets.CUI_CLOUD_KEY }} -Dcui_cloud_url=${{ secrets.CUI_CLOUD_URL }} -Pcui_cloud_url=${{ secrets.CUI_CLOUD_URL }}
|
||||
- name: Gradle :mirai-console-qqandroid:cuiCloudUpload
|
||||
run: ./gradlew :mirai-console-graphical:cuiCloudUpload -Dcui_cloud_key=${{ secrets.CUI_CLOUD_KEY }} -Pcui_cloud_key=${{ secrets.CUI_CLOUD_KEY }} -Dcui_cloud_url=${{ secrets.CUI_CLOUD_URL }} -Pcui_cloud_url=${{ secrets.CUI_CLOUD_URL }}
|
||||
|
||||
|
||||
# - name: Upload artifact
|
||||
# uses: actions/upload-artifact@v1.0.0
|
||||
# with:
|
||||
# # Artifact name
|
||||
# name: mirai-core
|
||||
# # Directory containing files to upload
|
||||
# path: "mirai-core/build/libs/mirai-core-*-all.jar"
|
||||
# - name: Upload artifact
|
||||
# uses: actions/upload-artifact@v1.0.0
|
||||
# with:
|
||||
# # Artifact name
|
||||
# name: mirai-core-qqandroid-all
|
||||
# # Directory containing files to upload
|
||||
# path: "mirai-core-qqandroid/build/libs/mirai-core-qqandroid-*-all.jar"
|
48
.github/workflows/shadow.yml
vendored
Normal file
48
.github/workflows/shadow.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: mirai-repo Publish
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Gradle clean
|
||||
run: ./gradlew clean
|
||||
- name: Gradle build
|
||||
run: ./gradlew build # if test's failed, don't publish
|
||||
- name: Gradle :mirai-console:githubUpload
|
||||
run: ./gradlew :mirai-console:githubUpload -Dgithub_token=${{ secrets.MAMOE_TOKEN }} -Pgithub_token=${{ secrets.MAMOE_TOKEN }}
|
||||
- name: Gradle :mirai-console-qqandroid:githubUpload
|
||||
run: ./gradlew :mirai-console-graphical:githubUpload -Dgithub_token=${{ secrets.MAMOE_TOKEN }} -Pgithub_token=${{ secrets.MAMOE_TOKEN }}
|
||||
|
||||
|
||||
# - name: Upload artifact
|
||||
# uses: actions/upload-artifact@v1.0.0
|
||||
# with:
|
||||
# # Artifact name
|
||||
# name: mirai-core
|
||||
# # Directory containing files to upload
|
||||
# path: "mirai-core/build/libs/mirai-core-*-all.jar"
|
||||
# - name: Upload artifact
|
||||
# uses: actions/upload-artifact@v1.0.0
|
||||
# with:
|
||||
# # Artifact name
|
||||
# name: mirai-core-qqandroid-all
|
||||
# # Directory containing files to upload
|
||||
# path: "mirai-core-qqandroid/build/libs/mirai-core-qqandroid-*-all.jar"
|
44
build.gradle
44
build.gradle
@ -1,44 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url 'https://mirrors.huaweicloud.com/repository/maven' }
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
|
||||
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:1.4-M1"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4-M1"
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' // don't use any other.
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
def keyProps = new Properties()
|
||||
def keyFile = file("local.properties")
|
||||
if (keyFile.exists()) keyFile.withInputStream { keyProps.load(it) }
|
||||
if (!keyProps.getProperty("sdk.dir", "").isEmpty()) {
|
||||
project.ext.set("isAndroidSDKAvailable", true)
|
||||
} else {
|
||||
project.ext.set("isAndroidSDKAvailable", false)
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = "net.mamoe"
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url "https://mirrors.huaweicloud.com/repository/maven" }
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
|
||||
}
|
||||
}
|
103
build.gradle.kts
Normal file
103
build.gradle.kts
Normal file
@ -0,0 +1,103 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import kotlin.math.pow
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
maven(url = "https://mirrors.huaweicloud.com/repository/maven")
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("com.github.jengelman.gradle.plugins:shadow:5.2.0")
|
||||
classpath("org.jetbrains.kotlin:kotlin-serialization:${Versions.Kotlin.stdlib}")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Kotlin.stdlib}")
|
||||
classpath("com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4") // don"t use any other.
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = "net.mamoe"
|
||||
|
||||
repositories {
|
||||
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
maven(url = "https://mirrors.huaweicloud.com/repository/maven")
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
afterEvaluate {
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
val kotlin =
|
||||
(this as ExtensionAware).extensions.getByName("kotlin") as? org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||
?: return@afterEvaluate
|
||||
|
||||
val githubUpload by tasks.creating {
|
||||
group = "mirai"
|
||||
dependsOn(tasks.getByName("shadowJar"))
|
||||
|
||||
doFirst {
|
||||
timeout.set(java.time.Duration.ofHours(3))
|
||||
findLatestFile()?.let { (_, file) ->
|
||||
val filename = file.name
|
||||
println("Uploading file $filename")
|
||||
runCatching {
|
||||
upload.GitHub.upload(
|
||||
file,
|
||||
"https://api.github.com/repos/mamoe/mirai-repo/contents/shadow/${project.name}/$filename",
|
||||
project
|
||||
)
|
||||
}.exceptionOrNull()?.let {
|
||||
System.err.println("GitHub Upload failed")
|
||||
it.printStackTrace() // force show stacktrace
|
||||
throw it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val cuiCloudUpload by tasks.creating {
|
||||
group = "mirai"
|
||||
dependsOn(tasks.getByName("shadowJar"))
|
||||
|
||||
doFirst {
|
||||
timeout.set(java.time.Duration.ofHours(3))
|
||||
findLatestFile()?.let { (_, file) ->
|
||||
val filename = file.name
|
||||
println("Uploading file $filename")
|
||||
runCatching {
|
||||
upload.CuiCloud.upload(
|
||||
file,
|
||||
project
|
||||
)
|
||||
}.exceptionOrNull()?.let {
|
||||
System.err.println("CuiCloud Upload failed")
|
||||
it.printStackTrace() // force show stacktrace
|
||||
throw it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Project.findLatestFile(): Map.Entry<String, File>? {
|
||||
return File(projectDir, "build/libs").walk()
|
||||
.filter { it.isFile }
|
||||
.onEach { println("all files=$it") }
|
||||
.filter { it.name.matches(Regex("""${project.name}-([0-9]|\.)*-all\.jar""")) }
|
||||
.onEach { println("matched file: ${it.name}") }
|
||||
.associateBy { it.nameWithoutExtension.substringAfterLast('-').replace("-all", "") }
|
||||
.onEach { println("versions: $it") }
|
||||
.maxBy {
|
||||
it.key.split('.').foldRightIndexed(0) { index: Int, s: String, acc: Int ->
|
||||
acc + 100.0.pow(2 - index).toInt() * (s.toIntOrNull() ?: 0)
|
||||
}
|
||||
}
|
||||
}
|
@ -4,4 +4,24 @@ plugins {
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets.all {
|
||||
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$version"
|
||||
fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
|
||||
|
||||
api("org.jsoup:jsoup:1.12.1")
|
||||
|
||||
api("com.google.code.gson:gson:2.8.6")
|
||||
api(kotlinx("coroutines-core", "1.3.3"))
|
||||
api(ktor("client-core", "1.3.2"))
|
||||
api(ktor("client-cio", "1.3.2"))
|
||||
api(ktor("client-json", "1.3.2"))
|
||||
}
|
134
buildSrc/src/main/kotlin/upload/CuiCloud.kt
Normal file
134
buildSrc/src/main/kotlin/upload/CuiCloud.kt
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package upload
|
||||
|
||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||
import io.ktor.client.request.forms.formData
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.isSuccess
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
object CuiCloud {
|
||||
private fun getUrl(project: Project): String {
|
||||
kotlin.runCatching {
|
||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
|
||||
val cui_cloud_url: String by project
|
||||
return cui_cloud_url
|
||||
}
|
||||
|
||||
System.getProperty("cui_cloud_url", null)?.let {
|
||||
return it.trim()
|
||||
}
|
||||
File(File(System.getProperty("user.dir")).parent, "/cuiUrl.txt").let { local ->
|
||||
if (local.exists()) {
|
||||
return local.readText().trim()
|
||||
}
|
||||
}
|
||||
|
||||
File(File(System.getProperty("user.dir")), "/cuiUrl.txt").let { local ->
|
||||
if (local.exists()) {
|
||||
return local.readText().trim()
|
||||
}
|
||||
}
|
||||
error("cannot find url for CuiCloud")
|
||||
}
|
||||
|
||||
private fun getKey(project: Project): String {
|
||||
kotlin.runCatching {
|
||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
|
||||
val cui_cloud_key: String by project
|
||||
return cui_cloud_key
|
||||
}
|
||||
|
||||
System.getProperty("cui_cloud_key", null)?.let {
|
||||
return it.trim()
|
||||
}
|
||||
File(File(System.getProperty("user.dir")).parent, "/cuiToken.txt").let { local ->
|
||||
if (local.exists()) {
|
||||
return local.readText().trim()
|
||||
}
|
||||
}
|
||||
|
||||
File(File(System.getProperty("user.dir")), "/cuiToken.txt").let { local ->
|
||||
if (local.exists()) {
|
||||
return local.readText().trim()
|
||||
}
|
||||
}
|
||||
|
||||
error("cannot find key for CuiCloud")
|
||||
}
|
||||
|
||||
fun upload(file: File, project: Project) {
|
||||
val cuiCloudUrl = getUrl(project)
|
||||
val key = getKey(project)
|
||||
|
||||
runBlocking {
|
||||
uploadToCuiCloud(
|
||||
cuiCloudUrl,
|
||||
key,
|
||||
"/mirai/${project.name}/${file.nameWithoutExtension}.mp4",
|
||||
file.readBytes()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@UseExperimental(ExperimentalStdlibApi::class)
|
||||
private suspend fun uploadToCuiCloud(
|
||||
cuiCloudUrl: String,
|
||||
cuiToken: String,
|
||||
filePath: String,
|
||||
content: ByteArray
|
||||
) {
|
||||
println("filePath=$filePath")
|
||||
println("content=${content.size / 1024 / 1024} MB")
|
||||
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Http.post<HttpResponse>(cuiCloudUrl) {
|
||||
body = MultiPartFormDataContent(
|
||||
formData {
|
||||
append("base64", Base64.getEncoder().encodeToString(content))
|
||||
append("filePath", filePath)
|
||||
append("large", "true")
|
||||
append("key", cuiToken)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
println(response.status)
|
||||
|
||||
val buffer = ByteArray(4096)
|
||||
val resp = buildList<Byte> {
|
||||
while (true) {
|
||||
val read = response.content.readAvailable(buffer, 0, buffer.size)
|
||||
if (read == -1) {
|
||||
break
|
||||
}
|
||||
addAll(buffer.toList().take(read))
|
||||
}
|
||||
}
|
||||
println(String(resp.toByteArray()))
|
||||
|
||||
if (!response.status.isSuccess()) {
|
||||
error("Cui cloud response: ${response.status}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <E> buildList(builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
return ArrayList<E>().apply(builderAction)
|
||||
}
|
178
buildSrc/src/main/kotlin/upload/GitHub.kt
Normal file
178
buildSrc/src/main/kotlin/upload/GitHub.kt
Normal file
@ -0,0 +1,178 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
||||
|
||||
package upload
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.features.HttpTimeout
|
||||
import io.ktor.client.request.put
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import org.jsoup.Connection
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
internal val Http = HttpClient(CIO) {
|
||||
engine {
|
||||
requestTimeout = 600_000
|
||||
}
|
||||
install(HttpTimeout) {
|
||||
socketTimeoutMillis = 600_000
|
||||
requestTimeoutMillis = 600_000
|
||||
connectTimeoutMillis = 600_000
|
||||
}
|
||||
}
|
||||
|
||||
object GitHub {
|
||||
|
||||
private fun getGithubToken(project: Project): String {
|
||||
kotlin.runCatching {
|
||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
|
||||
val github_token: String by project
|
||||
return github_token
|
||||
}
|
||||
|
||||
System.getProperty("github_token", null)?.let {
|
||||
return it.trim()
|
||||
}
|
||||
|
||||
File(File(System.getProperty("user.dir")).parent, "/token.txt").let { local ->
|
||||
if (local.exists()) {
|
||||
return local.readText().trim()
|
||||
}
|
||||
}
|
||||
|
||||
File(File(System.getProperty("user.dir")), "/token.txt").let { local ->
|
||||
if (local.exists()) {
|
||||
return local.readText().trim()
|
||||
}
|
||||
}
|
||||
|
||||
error(
|
||||
"Cannot find github token, " +
|
||||
"please specify by creating a file token.txt in project dir, " +
|
||||
"or by providing JVM parameter 'github_token'"
|
||||
)
|
||||
}
|
||||
|
||||
fun upload(file: File, url: String, project: Project) = runBlocking {
|
||||
val token = getGithubToken(project)
|
||||
println("token.length=${token.length}")
|
||||
Http.put<String>("$url?access_token=$token") {
|
||||
val sha = getGithubSha("mirai-repo", "shadow/${project.name}/${file.name}", "master", project)
|
||||
println("sha=$sha")
|
||||
val content = String(Base64.getEncoder().encode(file.readBytes()))
|
||||
body = """
|
||||
{
|
||||
"message": "automatically upload on release",
|
||||
"content": "$content"
|
||||
${if (sha == null) "" else """, "sha": "$sha" """}
|
||||
}
|
||||
""".trimIndent()
|
||||
}.let {
|
||||
println("Upload response: $it")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private suspend fun getGithubSha(
|
||||
repo: String,
|
||||
filePath: String,
|
||||
branch: String,
|
||||
project: Project
|
||||
): String? {
|
||||
fun String.asJson(): JsonObject {
|
||||
return JsonParser.parseString(this).asJsonObject
|
||||
}
|
||||
|
||||
/*
|
||||
* 只能获取1M以内/branch为master的sha
|
||||
* */
|
||||
class TargetTooLargeException() : Exception("Target TOO Large")
|
||||
|
||||
suspend fun getShaSmart(repo: String, filePath: String, project: Project): String? {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = Jsoup
|
||||
.connect(
|
||||
"https://api.github.com/repos/mamoe/$repo/contents/$filePath?access_token=" + getGithubToken(
|
||||
project
|
||||
)
|
||||
)
|
||||
.ignoreContentType(true)
|
||||
.ignoreHttpErrors(true)
|
||||
.method(Connection.Method.GET)
|
||||
.execute()
|
||||
if (response.statusCode() == 404) {
|
||||
null
|
||||
} else {
|
||||
val p = response.body().asJson()
|
||||
if (p.has("message") && p["message"].asString == "This API returns blobs up to 1 MB in size. The requested blob is too large to fetch via the API, but you can use the Git Data API to request blobs up to 100 MB in size.") {
|
||||
throw TargetTooLargeException()
|
||||
}
|
||||
p.get("sha").asString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getShaStupid(
|
||||
repo: String,
|
||||
filePath: String,
|
||||
branch: String,
|
||||
project: Project
|
||||
): String? {
|
||||
val resp = withContext(Dispatchers.IO) {
|
||||
Jsoup
|
||||
.connect(
|
||||
"https://api.github.com/repos/mamoe/$repo/git/ref/heads/$branch?access_token=" + getGithubToken(
|
||||
project
|
||||
)
|
||||
)
|
||||
.ignoreContentType(true)
|
||||
.ignoreHttpErrors(true)
|
||||
.method(Connection.Method.GET)
|
||||
.execute()
|
||||
}
|
||||
if (resp.statusCode() == 404) {
|
||||
println("Branch Not Found")
|
||||
return null
|
||||
}
|
||||
val info = resp.body().asJson().get("object").asJsonObject.get("url").asString
|
||||
var parentNode = withContext(Dispatchers.IO) {
|
||||
Jsoup.connect(info + "?access_token=" + getGithubToken(project)).ignoreContentType(true)
|
||||
.method(Connection.Method.GET)
|
||||
.execute().body().asJson().get("tree").asJsonObject.get("url").asString
|
||||
}
|
||||
filePath.split("/").forEach { subPath ->
|
||||
withContext(Dispatchers.IO) {
|
||||
Jsoup.connect(parentNode + "?access_token=" + getGithubToken(project)).ignoreContentType(true)
|
||||
.method(Connection.Method.GET).execute().body().asJson().get("tree").asJsonArray
|
||||
}.forEach list@{
|
||||
with(it.asJsonObject) {
|
||||
if (this.get("path").asString == subPath) {
|
||||
parentNode = this.get("url").asString
|
||||
return@list
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
check(parentNode.contains("/blobs/"))
|
||||
return parentNode.substringAfterLast("/")
|
||||
}
|
||||
|
||||
return if (branch == "master") {
|
||||
try {
|
||||
getShaSmart(repo, filePath, project)
|
||||
} catch (e: TargetTooLargeException) {
|
||||
getShaStupid(repo, filePath, branch, project)
|
||||
}
|
||||
} else {
|
||||
getShaStupid(repo, filePath, branch, project)
|
||||
}
|
||||
}
|
||||
}
|
@ -11,33 +11,18 @@ import org.gradle.kotlin.dsl.DependencyHandlerScope
|
||||
|
||||
object Versions {
|
||||
object Mirai {
|
||||
const val core = "0.31.0"
|
||||
const val console = "0.4.1"
|
||||
const val core = "0.32.0"
|
||||
const val console = "0.4.2"
|
||||
const val consoleGraphical = "0.0.5"
|
||||
const val consoleWrapper = "0.2.0"
|
||||
}
|
||||
|
||||
object Kotlin {
|
||||
const val stdlib = "1.4-M1"
|
||||
const val coroutines = "1.3.5-1.4-M1"
|
||||
const val atomicFU = "0.14.2-1.4-M1"
|
||||
const val serialization = "0.20.0-1.4-M1"
|
||||
const val ktor = "1.3.2-1.4-M1"
|
||||
|
||||
const val io = "0.1.16"
|
||||
const val coroutinesIo = "0.1.16"
|
||||
const val dokka = "0.10.1"
|
||||
const val stdlib = "1.3.71"
|
||||
const val coroutines = "1.3.5"
|
||||
const val serialization = "0.20.0"
|
||||
const val ktor = "1.3.2"
|
||||
}
|
||||
|
||||
object Android {
|
||||
const val androidGradlePlugin = "3.5.3"
|
||||
}
|
||||
|
||||
object Publishing {
|
||||
const val bintray = "1.8.4-jetbrains-3"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
|
@ -49,21 +49,6 @@ bintray {
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinVersion: String by rootProject.ext
|
||||
val atomicFuVersion: String by rootProject.ext
|
||||
val coroutinesVersion: String by rootProject.ext
|
||||
val kotlinXIoVersion: String by rootProject.ext
|
||||
val coroutinesIoVersion: String by rootProject.ext
|
||||
|
||||
val klockVersion: String by rootProject.ext
|
||||
val ktorVersion: String by rootProject.ext
|
||||
|
||||
val serializationVersion: String by rootProject.ext
|
||||
|
||||
fun kotlinx(id: String, version: String) = "org.jetbrains.kotlinx:kotlinx-$id:$version"
|
||||
|
||||
fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
|
||||
|
||||
dependencies {
|
||||
compileOnly("net.mamoe:mirai-core-jvm:${Versions.Mirai.core}")
|
||||
implementation(project(":mirai-console"))
|
||||
|
@ -85,7 +85,7 @@ class MiraiGraphicalUIController : Controller(), MiraiConsoleUI {
|
||||
}
|
||||
|
||||
override fun pushBot(bot: Bot) = Platform.runLater {
|
||||
cache[bot.uin]?.bot = bot
|
||||
cache[bot.id]?.bot = bot
|
||||
}
|
||||
|
||||
override fun pushVersion(consoleVersion: String, consoleBuild: String, coreVersion: String) {
|
||||
|
@ -15,7 +15,7 @@ tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>() {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
api("net.mamoe:mirai-core-qqandroid-jvm:${Versions.Mirai.core}")
|
||||
compileOnly("net.mamoe:mirai-core-qqandroid:${Versions.Mirai.core}")
|
||||
api(project(":mirai-console"))
|
||||
api(group = "com.googlecode.lanterna", name = "lanterna", version = "3.0.2")
|
||||
}
|
@ -97,8 +97,8 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
|
||||
}
|
||||
|
||||
override fun pushBot(bot: Bot) {
|
||||
botAdminCount[bot.uin] = 0
|
||||
screens.add(bot.uin)
|
||||
botAdminCount[bot.id] = 0
|
||||
screens.add(bot.id)
|
||||
drawFrame(this.getScreenName(currentScreenId))
|
||||
if (terminal is SwingTerminalFrame) {
|
||||
terminal.flush()
|
||||
|
@ -119,13 +119,4 @@ internal object ConsoleUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadConsole(version: String) {
|
||||
|
||||
/*
|
||||
tryNTimesOrQuit(3, "Failed to download Console, please seek for help") {
|
||||
Http.downloadMavenArchive("net/mamoe", getProjectName(), version)
|
||||
.saveToContent("${getProjectName()}-$version.jar")
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
@ -79,7 +79,7 @@ private class MiraiDownloaderImpl(
|
||||
val input= con.inputStream
|
||||
totalSize.addAndGet(con.contentLength)
|
||||
val outputStream = FileOutputStream(file)
|
||||
var len = -1
|
||||
var len: Int
|
||||
val buff = ByteArray(1024)
|
||||
while (input.read(buff).also { len = it } != -1) {
|
||||
totalDownload.addAndGet(buff.size)
|
||||
|
@ -32,7 +32,6 @@ dependencies {
|
||||
|
||||
testApi("net.mamoe:mirai-core-qqandroid-jvm:${Versions.Mirai.core}")
|
||||
testApi(kotlin("stdlib"))
|
||||
testApi("org.jsoup:jsoup:1.12.1")
|
||||
}
|
||||
|
||||
version = Versions.Mirai.console
|
||||
@ -103,4 +102,8 @@ compileKotlin.kotlinOptions {
|
||||
val compileTestKotlin: KotlinCompile by tasks
|
||||
compileTestKotlin.kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
@ -13,7 +13,6 @@ import kotlinx.coroutines.GlobalScope;
|
||||
import net.mamoe.mirai.event.Event;
|
||||
import net.mamoe.mirai.event.Listener;
|
||||
import net.mamoe.mirai.event.ListeningStatus;
|
||||
import net.mamoe.mirai.event.internal.EventInternalJvmKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@ -35,7 +34,7 @@ public final class Events {
|
||||
*/
|
||||
@NotNull
|
||||
public static <E extends Event> Listener<E> subscribe(@NotNull Class<E> eventClass, @NotNull Function<E, ListeningStatus> onEvent) {
|
||||
return EventInternalJvmKt._subscribeEventForJaptOnly(eventClass, GlobalScope.INSTANCE, onEvent);
|
||||
return EventsImplKt.subscribeEventForJaptOnly(eventClass, GlobalScope.INSTANCE, onEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,7 +48,7 @@ public final class Events {
|
||||
*/
|
||||
@NotNull
|
||||
public static <E extends Event> Listener<E> subscribeAlways(@NotNull Class<E> eventClass, @NotNull Consumer<E> onEvent) {
|
||||
return EventInternalJvmKt._subscribeEventForJaptOnly(eventClass, GlobalScope.INSTANCE, onEvent);
|
||||
return EventsImplKt.subscribeEventForJaptOnly(eventClass, GlobalScope.INSTANCE, onEvent);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,16 +9,13 @@
|
||||
|
||||
package net.mamoe.mirai.console
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.io.charsets.Charset
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.command.DefaultCommands
|
||||
import net.mamoe.mirai.console.plugins.PluginManager
|
||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
||||
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
||||
import net.mamoe.mirai.utils.io.encodeToString
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
@ -29,6 +26,7 @@ object MiraiConsole {
|
||||
*/
|
||||
const val build = "Pkmon"
|
||||
lateinit var version: String
|
||||
internal set
|
||||
|
||||
/**
|
||||
* 获取从Console登陆上的Bot, Bots
|
||||
@ -36,7 +34,7 @@ object MiraiConsole {
|
||||
val bots get() = Bot.instances
|
||||
|
||||
fun getBotOrNull(uin: Long): Bot? {
|
||||
return bots.asSequence().mapNotNull { it.get() }.firstOrNull { it.uin == uin }
|
||||
return bots.asSequence().mapNotNull { it.get() }.firstOrNull { it.id == uin }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,64 +96,12 @@ object MiraiConsole {
|
||||
*/
|
||||
fun stop() {
|
||||
PluginManager.disablePlugins()
|
||||
CommandManager.cancel()
|
||||
CommandManager.cancel()
|
||||
try {
|
||||
bots.forEach {
|
||||
it.get()?.close()
|
||||
}
|
||||
} catch (ignored: Exception) { }
|
||||
}
|
||||
|
||||
@Suppress("RedundantSuspendModifier") // binary compatibility
|
||||
@Deprecated(
|
||||
"Please use CommandManager directly, this will be removed in later release",
|
||||
ReplaceWith(
|
||||
"CommandManager",
|
||||
"net.mamoe.mirai.console.command.CommandManager"
|
||||
),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
object CommandProcessor {
|
||||
@Deprecated(
|
||||
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||
"CommandManager.runConsoleCommand(command)",
|
||||
"net.mamoe.mirai.console.command.CommandManager"
|
||||
), level = DeprecationLevel.ERROR
|
||||
)
|
||||
suspend fun runConsoleCommand(command: String) {
|
||||
CommandManager.runCommand(ConsoleCommandSender, command)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||
"CommandManager.runCommand(sender, command)",
|
||||
"net.mamoe.mirai.console.command.CommandManager"
|
||||
), level = DeprecationLevel.ERROR
|
||||
)
|
||||
suspend fun runCommand(sender: CommandSender, command: String) {
|
||||
CommandManager.runCommand(sender, command)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||
"CommandManager.runCommand(command)",
|
||||
"net.mamoe.mirai.console.command.CommandManager",
|
||||
"net.mamoe.mirai.console.command.ConsoleCommandSender"
|
||||
), level = DeprecationLevel.ERROR
|
||||
)
|
||||
fun runConsoleCommandBlocking(command: String) =
|
||||
runBlocking { CommandManager.runCommand(ConsoleCommandSender, command) }
|
||||
|
||||
|
||||
@Suppress("unused")
|
||||
@Deprecated(
|
||||
"Please use CommandManager directly, this will be removed in later release", ReplaceWith(
|
||||
"CommandManager.runCommand(sender, command)",
|
||||
"net.mamoe.mirai.console.command.CommandManager"
|
||||
), level = DeprecationLevel.ERROR
|
||||
)
|
||||
fun runCommandBlocking(sender: CommandSender, command: String) = runBlocking {
|
||||
CommandManager.runCommand(sender, command)
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,4 +154,9 @@ internal val Throwable.stacktraceString: String
|
||||
get() =
|
||||
ByteArrayOutputStream().apply {
|
||||
printStackTrace(PrintStream(this))
|
||||
}.use { it.toByteArray().encodeToString() }
|
||||
}.use { it.toByteArray().encodeToString() }
|
||||
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun ByteArray.encodeToString(charset: Charset = Charsets.UTF_8): String =
|
||||
kotlinx.io.core.String(this, charset = charset)
|
||||
|
@ -2,34 +2,34 @@ package net.mamoe.mirai.console.center
|
||||
|
||||
interface PluginCenter {
|
||||
|
||||
companion object{
|
||||
val Default:PluginCenter = CuiPluginCenter
|
||||
companion object {
|
||||
val Default: PluginCenter = CuiPluginCenter
|
||||
}
|
||||
|
||||
data class PluginInsight(
|
||||
val name:String,
|
||||
val version:String,
|
||||
val coreVersion:String,
|
||||
val consoleVersion:String,
|
||||
val author:String,
|
||||
val name: String,
|
||||
val version: String,
|
||||
val coreVersion: String,
|
||||
val consoleVersion: String,
|
||||
val author: String,
|
||||
val description: String,
|
||||
val tags:List<String>,
|
||||
val commands:List<String>,
|
||||
val tags: List<String>,
|
||||
val commands: List<String>
|
||||
)
|
||||
|
||||
data class PluginInfo(
|
||||
val name:String,
|
||||
val version:String,
|
||||
val coreVersion:String,
|
||||
val consoleVersion:String,
|
||||
val tags:List<String>,
|
||||
val author:String,
|
||||
val contact:String,
|
||||
val name: String,
|
||||
val version: String,
|
||||
val coreVersion: String,
|
||||
val consoleVersion: String,
|
||||
val tags: List<String>,
|
||||
val author: String,
|
||||
val contact: String,
|
||||
val description: String,
|
||||
val usage:String,
|
||||
val vcs:String,
|
||||
val commands:String,
|
||||
val changeLog:List<String>
|
||||
val usage: String,
|
||||
val vcs: String,
|
||||
val commands: String,
|
||||
val changeLog: List<String>
|
||||
)
|
||||
|
||||
/**
|
||||
@ -37,7 +37,7 @@ interface PluginCenter {
|
||||
* 能获取到多少由实际的PluginCenter决定
|
||||
* 返回 插件名->Insight
|
||||
*/
|
||||
suspend fun fetchPlugin(page: Int) :Map<String,PluginInsight>
|
||||
suspend fun fetchPlugin(page: Int): Map<String, PluginInsight>
|
||||
|
||||
/**
|
||||
* 尝试获取到某个插件by全名, case sensitive
|
||||
|
@ -50,22 +50,10 @@ interface Command {
|
||||
*/
|
||||
inline fun Command.register(commandOwner: CommandOwner) = CommandManager.register(commandOwner,this)
|
||||
|
||||
|
||||
/**
|
||||
* 构造并注册一个指令
|
||||
*/
|
||||
@Deprecated("this will be removed in next few release")
|
||||
object AnonymousCommandOwner:CommandOwner
|
||||
@Deprecated("this will become internal in next few release, please use PluginBase.registerCommand() for plugin")
|
||||
inline fun registerCommand(builder: CommandBuilder.() -> Unit): Command {
|
||||
return CommandBuilder().apply(builder).register(AnonymousCommandOwner)
|
||||
}
|
||||
|
||||
internal inline fun registerConsoleCommands(builder: CommandBuilder.() -> Unit):Command{
|
||||
return CommandBuilder().apply(builder).register(ConsoleCommandOwner)
|
||||
}
|
||||
|
||||
|
||||
inline fun PluginBase.registerCommand(builder: CommandBuilder.() -> Unit):Command{
|
||||
return CommandBuilder().apply(builder).register(this.asCommandOwner())
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import net.mamoe.mirai.console.utils.removeManager
|
||||
import net.mamoe.mirai.contact.sendMessage
|
||||
import net.mamoe.mirai.event.subscribeMessages
|
||||
import net.mamoe.mirai.getFriendOrNull
|
||||
import net.mamoe.mirai.utils.FileBasedDeviceInfo
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
import java.util.*
|
||||
|
||||
@ -117,7 +116,7 @@ object DefaultCommands {
|
||||
try {
|
||||
MiraiConsole.frontEnd.prePushBot(qqNumber)
|
||||
val bot = Bot(qqNumber, qqPassword) {
|
||||
+FileBasedDeviceInfo
|
||||
fileBasedDeviceInfo()
|
||||
this.loginSolver = MiraiConsole.frontEnd.createLoginSolver()
|
||||
this.botLoggerSupplier = {
|
||||
SimpleLogger("BOT $qqNumber]") { _, message, e ->
|
||||
@ -168,10 +167,10 @@ object DefaultCommands {
|
||||
val bot = args[0]
|
||||
var find = false
|
||||
MiraiConsole.bots.forEach {
|
||||
if (it.get()?.uin.toString().contains(bot)) {
|
||||
if (it.get()?.id.toString().contains(bot)) {
|
||||
find = true
|
||||
appendMessage(
|
||||
"" + it.get()?.uin + ": 在线中; 好友数量:" + it.get()?.friends?.size + "; 群组数量:" + it.get()
|
||||
"" + it.get()?.id + ": 在线中; 好友数量:" + it.get()?.friends?.size + "; 群组数量:" + it.get()
|
||||
?.groups?.size
|
||||
)
|
||||
}
|
||||
|
@ -7,10 +7,26 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
package net.mamoe.mirai.console.events;
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.Listener
|
||||
import net.mamoe.mirai.event.ListeningStatus
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.internal._subscribeEventForJaptOnly
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Function
|
||||
|
||||
internal fun <E : Event> broadcast(e: E): E = runBlocking { e.broadcast() }
|
||||
|
||||
internal fun <E : Event> Class<E>.subscribeEventForJaptOnly(
|
||||
scope: CoroutineScope,
|
||||
onEvent: Function<E, ListeningStatus>
|
||||
): Listener<E> = _subscribeEventForJaptOnly(scope, onEvent)
|
||||
|
||||
internal fun <E : Event> Class<E>.subscribeEventForJaptOnly(scope: CoroutineScope, onEvent: Consumer<E>): Listener<E> =
|
||||
_subscribeEventForJaptOnly(scope, onEvent)
|
@ -17,8 +17,8 @@ import com.moandjiezana.toml.Toml
|
||||
import com.moandjiezana.toml.TomlWriter
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UnstableDefault
|
||||
import net.mamoe.mirai.console.encodeToString
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.encodeToString
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
@ -486,7 +486,7 @@ abstract class FileConfigImpl internal constructor(
|
||||
|
||||
}
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
class JsonConfig internal constructor(
|
||||
content: String
|
||||
) : FileConfigImpl(content) {
|
||||
@ -513,7 +513,7 @@ class JsonConfig internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
class YamlConfig internal constructor(content: String) : FileConfigImpl(content) {
|
||||
constructor(file: File) : this(file.readText()) {
|
||||
this.file = file
|
||||
@ -536,7 +536,7 @@ class YamlConfig internal constructor(content: String) : FileConfigImpl(content)
|
||||
|
||||
}
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
class TomlConfig internal constructor(content: String) : FileConfigImpl(content) {
|
||||
constructor(file: File) : this(file.readText()) {
|
||||
this.file = file
|
||||
|
@ -16,8 +16,8 @@ import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.Command
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.encodeToString
|
||||
import net.mamoe.mirai.utils.SimpleLogger
|
||||
import net.mamoe.mirai.utils.io.encodeToString
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.lang.reflect.Constructor
|
||||
|
@ -24,23 +24,23 @@ internal object BotManagers {
|
||||
}
|
||||
|
||||
fun Bot.addManager(long: Long) {
|
||||
BOT_MANAGERS.putIfAbsent(this.uin.toString(), mutableListOf<Long>())
|
||||
BOT_MANAGERS[this.uin.toString()] =
|
||||
(BOT_MANAGERS.getLongList(this.uin.toString()) as MutableList<Long>).apply { add(long) }
|
||||
BOT_MANAGERS.putIfAbsent(this.id.toString(), mutableListOf<Long>())
|
||||
BOT_MANAGERS[this.id.toString()] =
|
||||
(BOT_MANAGERS.getLongList(this.id.toString()) as MutableList<Long>).apply { add(long) }
|
||||
BotManagers.config.save()
|
||||
}
|
||||
|
||||
fun Bot.removeManager(long: Long) {
|
||||
BOT_MANAGERS.putIfAbsent(this.uin.toString(), mutableListOf<Long>())
|
||||
BOT_MANAGERS[this.uin.toString()] =
|
||||
(BOT_MANAGERS.getLongList(this.uin.toString()) as MutableList<Long>).apply { add(long) }
|
||||
BOT_MANAGERS.putIfAbsent(this.id.toString(), mutableListOf<Long>())
|
||||
BOT_MANAGERS[this.id.toString()] =
|
||||
(BOT_MANAGERS.getLongList(this.id.toString()) as MutableList<Long>).apply { add(long) }
|
||||
BotManagers.config.save()
|
||||
}
|
||||
|
||||
val Bot.managers: List<Long>
|
||||
get() {
|
||||
BOT_MANAGERS.putIfAbsent(this.uin.toString(), mutableListOf<Long>())
|
||||
return BOT_MANAGERS.getLongList(this.uin.toString())
|
||||
BOT_MANAGERS.putIfAbsent(this.id.toString(), mutableListOf<Long>())
|
||||
return BOT_MANAGERS.getLongList(this.id.toString())
|
||||
}
|
||||
|
||||
fun Bot.checkManager(long: Long): Boolean {
|
||||
|
Loading…
Reference in New Issue
Block a user