diff --git a/mvnw.cmd b/mvnw.cmd index 249bdf3..d8d70f7 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -32,7 +32,7 @@ @SET __MVNW_ERROR__= @SET __MVNW_PSMODULEP_SAVE=%PSModulePath% @SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-info.alinadace.sakuramiki.service.randomphoto.domain.Content -Raw '%~f0'))) -NoNewScope}"`) DO @( IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) ) @SET PSModulePath=%__MVNW_PSMODULEP_SAVE% @@ -51,7 +51,7 @@ if ($env:MVNW_VERBOSE -eq "true") { } # calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +$distributionUrl = (Get-info.alinadace.sakuramiki.service.randomphoto.domain.Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl if (!$distributionUrl) { Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" } @@ -121,7 +121,7 @@ if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { $webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null # If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +$distributionSha256Sum = (Get-info.alinadace.sakuramiki.service.randomphoto.domain.Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum if ($distributionSha256Sum) { if ($USE_MVND) { Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." diff --git a/pom.xml b/pom.xml index 4896fd3..db7dccc 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,8 @@ info.alinadace sakura-miki 0.0.1-SNAPSHOT - sakuramiki - sakuramiki + Sakura-Miki + Sakura-Miki @@ -127,6 +127,21 @@ org.springframework.boot spring-boot-starter-actuator + + + com.beust + klaxon + 5.6 + + + io.github.1530624156 + AlistUtil + 1.0.0-spring + + + com.squareup.okhttp3 + okhttp + diff --git a/src/main/kotlin/info/alinadace/sakuramiki/service/ExampleService.kt b/src/main/kotlin/info/alinadace/sakuramiki/service/ExampleService.kt index 2ffc308..cdb74b9 100644 --- a/src/main/kotlin/info/alinadace/sakuramiki/service/ExampleService.kt +++ b/src/main/kotlin/info/alinadace/sakuramiki/service/ExampleService.kt @@ -34,7 +34,7 @@ class ExampleService : Service { return true } } - return true + return false } /** diff --git a/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/RandomPhotoService.kt b/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/RandomPhotoService.kt new file mode 100644 index 0000000..a1932c3 --- /dev/null +++ b/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/RandomPhotoService.kt @@ -0,0 +1,69 @@ +package info.alinadace.sakuramiki.service.randomphoto + +import com.mavis.service.AlistService +import info.alinadace.sakuramiki.annotation.BotFunction +import info.alinadace.sakuramiki.service.Service +import info.alinadace.sakuramiki.service.randomphoto.domain.FileList +import info.alinadace.sakuramiki.service.randomphoto.domain.SingleFile +import info.alinadace.sakuramiki.util.okHttpClient +import io.github.kloping.qqbot.api.v2.FriendMessageEvent +import io.github.kloping.qqbot.api.v2.GroupMessageEvent +import io.github.kloping.qqbot.api.v2.MessageV2Event +import io.github.kloping.qqbot.entities.ex.Image +import io.github.kloping.qqbot.entities.ex.PlainText +import jakarta.annotation.Resource +import okhttp3.Request + +/** + * @author Kane + * @since 2024/11/11 19:26 + */ +@BotFunction(FriendMessageEvent::class, GroupMessageEvent::class) +class RandomPhotoService : Service { + + @Resource + lateinit var alistService: AlistService + + /** + * 服务入口 + */ + override fun entrance(event: MessageV2Event): Boolean { + val chain = event.message + if (chain.size == 1 && chain[0] is PlainText && chain[0].toString() == "#photo") { + return true + } + return true + } + + /** + * 服务行为 + */ + override fun active(event: MessageV2Event) { + val fileList = alistService.getAlistFileList("/VRChat-Photo") + val files = FileList.fromJson(fileList) + if (files.code != 200L) { + event.send("文件列表获取失败") + } + val content = files.data.content.filter { x -> !x.isDir } + if (content.isEmpty()) { + event.send("暂无照片") + return + } + val randomFile = content.random() + val fileInfo = alistService.getAlistFileInfo("/VRChat-Photo/" + randomFile.name, "") + val file = SingleFile.fromJson(fileInfo) + if (file.code != 200L) { + event.send("文件获取失败") + return + } + event.send("图片下载中...") + val request = Request.Builder().get().url(file.data.rawURL).build() + val imageByte = okHttpClient.newCall(request).execute().body?.bytes(); + if (imageByte == null) { + event.send("图片下载失败") + return + } + val image = Image(imageByte) + event.send(image) + } +} diff --git a/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/FileList.kt b/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/FileList.kt new file mode 100644 index 0000000..12b8ef9 --- /dev/null +++ b/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/FileList.kt @@ -0,0 +1,128 @@ +package info.alinadace.sakuramiki.service.randomphoto.domain + +// To parse the JSON, install jackson-module-kotlin and do: +// +// val response = FileList.fromJson(jsonString) + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.PropertyNamingStrategies +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue + + +data class FileList( + /** + * 状态码 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val code: Long, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val data: Data, + + /** + * 信息 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val message: String +) { + + fun toJson() = mapper.writeValueAsString(this) + + companion object { + private var mapper = jacksonObjectMapper().apply { + propertyNamingStrategy = PropertyNamingStrategies.LOWER_CAMEL_CASE + setSerializationInclusion(JsonInclude.Include.NON_NULL) + } + + fun fromJson(json: String) = mapper.readValue(json) + } + + data class Data( + /** + * 内容 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val content: List, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val header: String, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val provider: String, + + /** + * 说明 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val readme: String, + + /** + * 总数 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val total: Long, + + /** + * 是否可写入 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val write: Boolean + ) { + data class Content( + /** + * 创建时间 + */ + val created: String? = null, + + @get:JsonProperty("hash_info") @field:JsonProperty("hash_info") + val hashInfo: Any? = null, + + val hashinfo: String? = null, + + /** + * 是否是文件夹 + */ + @get:JsonProperty("is_dir", required = true) @field:JsonProperty("is_dir", required = true) + val isDir: Boolean, + + /** + * 修改时间 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val modified: String, + + /** + * 文件名 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val name: String, + + /** + * 签名 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val sign: String, + + /** + * 大小 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val size: Long, + + /** + * 缩略图 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val thumb: String, + + /** + * 类型 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val type: Long + ) + } +} + diff --git a/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/SingleFile.kt b/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/SingleFile.kt new file mode 100644 index 0000000..17b5f87 --- /dev/null +++ b/src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/SingleFile.kt @@ -0,0 +1,117 @@ +package info.alinadace.sakuramiki.service.randomphoto.domain +// To parse the JSON, install jackson-module-kotlin and do: +// +// val response = SingleFile.fromJson(jsonString) + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.PropertyNamingStrategies +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue + + +data class SingleFile( + /** + * 状态码 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val code: Long, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val data: Data, + + /** + * 信息 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val message: String +) { + + fun toJson() = mapper.writeValueAsString(this) + + companion object { + private val mapper = jacksonObjectMapper().apply { + propertyNamingStrategy = PropertyNamingStrategies.LOWER_CAMEL_CASE + setSerializationInclusion(JsonInclude.Include.NON_NULL) + } + + fun fromJson(json: String) = mapper.readValue(json) + } + + data class Data( + /** + * 创建时间 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val created: String, + + @get:JsonProperty("hash_info") @field:JsonProperty("hash_info") + val hashInfo: Any? = null, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val hashinfo: String, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val header: String, + + /** + * 是否是文件夹 + */ + @get:JsonProperty("is_dir", required = true) @field:JsonProperty("is_dir", required = true) + val isDir: Boolean, + + /** + * 修改时间 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val modified: String, + + /** + * 文件名 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val name: String, + + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val provider: String, + + /** + * 原始url + */ + @get:JsonProperty("raw_url", required = true) @field:JsonProperty("raw_url", required = true) + val rawURL: String, + + /** + * 说明 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val readme: String, + + val related: Any? = null, + + /** + * 签名 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val sign: String, + + /** + * 大小 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val size: Long, + + /** + * 缩略图 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val thumb: String, + + /** + * 类型 + */ + @get:JsonProperty(required = true) @field:JsonProperty(required = true) + val type: Long + ) +} + diff --git a/src/main/kotlin/info/alinadace/sakuramiki/util/OkHttp.kt b/src/main/kotlin/info/alinadace/sakuramiki/util/OkHttp.kt new file mode 100644 index 0000000..7d6b5f0 --- /dev/null +++ b/src/main/kotlin/info/alinadace/sakuramiki/util/OkHttp.kt @@ -0,0 +1,12 @@ +package info.alinadace.sakuramiki.util + +import okhttp3.OkHttpClient + +/** + * @author Kane + * @since 2024/11/11 20:39 + */ + +// 创建 OkHttpClient 实例 +val okHttpClient = OkHttpClient.Builder() + .build() diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 219505a..c60bb00 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,3 +12,8 @@ bot: token: sq3CZjEpK7Z65s2xuyhwp8WVBqvx35XP app-secret: Wgq0BMXit5HTfr3GTgt6JXlzDRgvAPet admin: 59EC2526FBCC1EC5F851187C0F4F8BA5 + +alist: + alist-base-url: https://alist.alina-dace.info + alist-username: admin + alist-password: vF7Wb2vo