From fbfb1c1a7fea6e21cf39ab640a54d5ec10e284e0 Mon Sep 17 00:00:00 2001
From: Grand-cocoa
<1075576561@qq.com49111108+grand-cocoa@users.noreply.github.com>
Date: Mon, 11 Nov 2024 20:48:56 +0800
Subject: [PATCH] =?UTF-8?q?feat(service):=20=E6=B7=BB=E5=8A=A0=E9=9A=8F?=
=?UTF-8?q?=E6=9C=BA=E7=85=A7=E7=89=87=E6=9C=8D=E5=8A=A1-=20=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=20RandomPhotoService=20=E7=B1=BB=E5=AE=9E=E7=8E=B0?=
=?UTF-8?q?=E9=9A=8F=E6=9C=BA=E7=85=A7=E7=89=87=E5=8A=9F=E8=83=BD=20-=20?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=20FileList=20=E5=92=8C=20SingleFile=20?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=A8=A1=E5=9E=8B=E7=94=A8=E4=BA=8E=E8=A7=A3?=
=?UTF-8?q?=E6=9E=90=20JSON=20=E5=93=8D=E5=BA=94=20-=20=E9=9B=86=E6=88=90?=
=?UTF-8?q?=20AlistService=20=E8=8E=B7=E5=8F=96=E6=96=87=E4=BB=B6=E5=88=97?=
=?UTF-8?q?=E8=A1=A8=E5=92=8C=E6=96=87=E4=BB=B6=E4=BF=A1=E6=81=AF=20-=20?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8=20OkHttpClient=20=E4=B8=8B=E8=BD=BD=E5=9B=BE?=
=?UTF-8?q?=E7=89=87=20-=20=E6=9B=B4=E6=96=B0=20application.yml=20?=
=?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=B7=BB=E5=8A=A0=20AList=20?=
=?UTF-8?q?=E7=9B=B8=E5=85=B3=E8=AE=BE=E7=BD=AE=20-=20=E4=BF=AE=E6=94=B9?=
=?UTF-8?q?=20ExampleService=20=E4=B8=AD=E7=9A=84=20entrance=20=E6=96=B9?=
=?UTF-8?q?=E6=B3=95=E8=BF=94=E5=9B=9E=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
mvnw.cmd | 6 +-
pom.xml | 19 ++-
.../sakuramiki/service/ExampleService.kt | 2 +-
.../service/randomphoto/RandomPhotoService.kt | 69 ++++++++++
.../service/randomphoto/domain/FileList.kt | 128 ++++++++++++++++++
.../service/randomphoto/domain/SingleFile.kt | 117 ++++++++++++++++
.../info/alinadace/sakuramiki/util/OkHttp.kt | 12 ++
src/main/resources/application.yml | 5 +
8 files changed, 352 insertions(+), 6 deletions(-)
create mode 100644 src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/RandomPhotoService.kt
create mode 100644 src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/FileList.kt
create mode 100644 src/main/kotlin/info/alinadace/sakuramiki/service/randomphoto/domain/SingleFile.kt
create mode 100644 src/main/kotlin/info/alinadace/sakuramiki/util/OkHttp.kt
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