feat: add image bed command
This commit is contained in:
31 files changed
+113
-63
No files matched your search
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/8/29
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
|
||||
fun Long.isSameDay(timestamp2: Long): Boolean {
|
||||
val zoneId = ZoneId.of("Asia/Shanghai")
|
||||
val date1 = Instant.ofEpochSecond(this).atZone(zoneId).toLocalDate()
|
||||
val date2 = Instant.ofEpochSecond(timestamp2).atZone(zoneId).toLocalDate()
|
||||
return date1 == date2
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/9/21
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import com.madgag.gif.fmsware.AnimatedGifEncoder
|
||||
import com.madgag.gif.fmsware.GifDecoder
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun GifDecoder.makeGif(frames: List<BufferedImage>): ByteArray {
|
||||
val estimatedSize = frames.size * 50 * 1024
|
||||
val byteArrayOutputStream = ByteArrayOutputStream(estimatedSize)
|
||||
val encoder = AnimatedGifEncoder()
|
||||
encoder.start(byteArrayOutputStream)
|
||||
encoder.setRepeat(0)
|
||||
val delays = frames.indices.map { this.getDelay(this.frameCount - it - 1) }
|
||||
frames.indices.forEach { i ->
|
||||
encoder.setDelay(delays[i])
|
||||
encoder.addFrame(frames[i])
|
||||
}
|
||||
encoder.finish()
|
||||
return byteArrayOutputStream.toByteArray()
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/9/12
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import cn.rtast.fancybot.configManager
|
||||
import java.awt.Graphics2D
|
||||
import java.awt.geom.Ellipse2D
|
||||
import java.awt.geom.RoundRectangle2D
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
|
||||
private fun BufferedImage.getScaledWidth(maxWidth: Double, maxHeight: Double): Pair<Int, Int> {
|
||||
val originalWidth = this.getWidth(null)
|
||||
val originalHeight = this.getHeight(null)
|
||||
val widthScale = maxWidth / originalWidth
|
||||
val heightScale = maxHeight / originalHeight
|
||||
val scale = minOf(widthScale, heightScale)
|
||||
val targetWidth = (originalWidth * scale).toInt()
|
||||
val targetHeight = (originalHeight * scale).toInt()
|
||||
return targetWidth to targetHeight
|
||||
}
|
||||
|
||||
fun Graphics2D.drawCustomImage(
|
||||
image: BufferedImage,
|
||||
x: Int,
|
||||
y: Int,
|
||||
maxWidth: Double,
|
||||
maxHeight: Double,
|
||||
clip: Boolean = false
|
||||
) {
|
||||
val (targetWidth, targetHeight) = image.getScaledWidth(maxWidth, maxHeight)
|
||||
if (clip) {
|
||||
this.clip = RoundRectangle2D.Float(
|
||||
x.toFloat(),
|
||||
y.toFloat(),
|
||||
targetWidth.toFloat(),
|
||||
targetHeight.toFloat(),
|
||||
30.toFloat(),
|
||||
30.toFloat()
|
||||
)
|
||||
}
|
||||
this.drawImage(image, x, y, targetWidth, targetHeight, null)
|
||||
this.clip = null
|
||||
}
|
||||
|
||||
fun Graphics2D.drawCircularImage(
|
||||
image: BufferedImage,
|
||||
x: Int,
|
||||
y: Int,
|
||||
maxWidth: Double,
|
||||
maxHeight: Double,
|
||||
) {
|
||||
val (targetWidth, targetHeight) = image.getScaledWidth(maxWidth, maxHeight)
|
||||
val circle = Ellipse2D.Double(x.toDouble(), y.toDouble(), targetWidth.toDouble(), targetHeight.toDouble())
|
||||
this.clip = circle
|
||||
this.drawImage(image, x, y, targetWidth, targetHeight, null)
|
||||
this.clip = null
|
||||
}
|
||||
|
||||
fun BufferedImage.scaleImage(size: Pair<Int, Int>): BufferedImage {
|
||||
val scaledImage = BufferedImage(size.first, size.second, this.type)
|
||||
val graphics2d = scaledImage.createGraphics()
|
||||
graphics2d.drawImage(this, 0, 0, size.first, size.second, null)
|
||||
graphics2d.dispose()
|
||||
return scaledImage
|
||||
}
|
||||
|
||||
fun ByteArray.toBufferedImage(): BufferedImage {
|
||||
ByteArrayInputStream(this).use { inputStream ->
|
||||
return ImageIO.read(inputStream)
|
||||
}
|
||||
}
|
||||
|
||||
fun BufferedImage.toByteArray(): ByteArray {
|
||||
ByteArrayOutputStream().use { outputStream ->
|
||||
ImageIO.write(this, configManager.imageType.typeName, outputStream)
|
||||
return outputStream.toByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
fun Graphics2D.drawCenteredText(text: String, x: Int, y: Int) {
|
||||
val metrics = this.fontMetrics
|
||||
val textWidth = metrics.stringWidth(text)
|
||||
val textHeight = metrics.height
|
||||
val drawX = x - textWidth / 2
|
||||
val drawY = y + textHeight / 2
|
||||
this.drawString(text, drawX, drawY)
|
||||
}
|
||||
|
||||
fun Graphics2D.drawString(text: String, x: Int, y: Int, maxWidth: Int) {
|
||||
val fm = this.fontMetrics
|
||||
val lineHeight = fm.height
|
||||
var curY = y
|
||||
val words = text.split(" ")
|
||||
val line = StringBuilder()
|
||||
for (word in words) {
|
||||
if (fm.stringWidth("$line$word ") <= maxWidth) {
|
||||
line.append(word).append(" ")
|
||||
} else {
|
||||
this.drawString(line.toString(), x, curY)
|
||||
curY += lineHeight
|
||||
line.setLength(0)
|
||||
line.append(word).append(" ")
|
||||
}
|
||||
}
|
||||
if (line.isNotEmpty()) {
|
||||
this.drawString(line.toString(), x, curY)
|
||||
}
|
||||
}
|
||||
|
||||
fun BufferedImage.isFullyTransparent(): Boolean {
|
||||
val width = this.width
|
||||
val height = this.height
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val pixel = this.getRGB(x, y)
|
||||
if ((pixel shr 24) != 0x00) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/10/8
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import cn.rtast.fancybot.configManager
|
||||
import cn.rtast.fancybot.entity.github.UploadContentPayload
|
||||
import cn.rtast.fancybot.entity.github.UploadContentResponse
|
||||
import cn.rtast.fancybot.util.Http
|
||||
import cn.rtast.fancybot.util.str.encodeToBase64
|
||||
import cn.rtast.fancybot.util.str.proxy
|
||||
import cn.rtast.fancybot.util.str.toJson
|
||||
import java.util.UUID
|
||||
|
||||
object ImageBed {
|
||||
|
||||
private val imageBedUrl =
|
||||
"https://api.github.com/repos/${configManager.githubUser}/${configManager.githubImageRepo}/contents".proxy
|
||||
|
||||
fun upload(file: ByteArray, fileType: String = ""): String {
|
||||
val body = UploadContentPayload("uploadImage", file.encodeToBase64()).toJson()
|
||||
val response = Http.put<UploadContentResponse>(
|
||||
"$imageBedUrl/${UUID.randomUUID()}${if (fileType.isNotBlank()) ".$fileType" else ""}", body,
|
||||
mapOf("Authorization" to "Bearer ${configManager.githubKey}")
|
||||
).content.name
|
||||
return "https://raw.githubusercontent.com/${configManager.githubUser}/${configManager.githubImageRepo}/refs/heads/main/$response".proxy
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/9/5
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import cn.rtast.fancybot.*
|
||||
import cn.rtast.fancybot.util.Http
|
||||
import cn.rtast.rob.ROneBotFactory
|
||||
import cn.rtast.rob.util.ob.OneBotListener
|
||||
import java.io.File
|
||||
import kotlin.random.Random
|
||||
|
||||
fun randomBooleanWithProbability(probability: Double): Boolean {
|
||||
val randomValue = Random.nextInt(100)
|
||||
return randomValue <= (probability * 100)
|
||||
}
|
||||
|
||||
suspend fun OneBotListener.getUserName(groupId: Long, userId: Long): String {
|
||||
val info = this.getGroupMemberInfo(groupId, userId)
|
||||
return info.card ?: info.nickname
|
||||
}
|
||||
|
||||
fun initCommandAndItem(rob: ROneBotFactory) {
|
||||
val commandManager = rob.commandManager
|
||||
commands.forEach { commandManager.register(it) }
|
||||
items.forEach { itemManager.register(it) }
|
||||
tasks.forEach { rob.scheduler.scheduleTask(it.value, 1000L, it.key) }
|
||||
}
|
||||
|
||||
fun initFilesDir() {
|
||||
File("$ROOT_PATH/caches/images").also { it.mkdirs() }
|
||||
File("$ROOT_PATH/logs").also { it.mkdirs() }
|
||||
}
|
||||
|
||||
fun initSetuIndex() {
|
||||
val file = File("$ROOT_PATH/caches/pixiv_index_v3.json")
|
||||
if (!file.exists()) {
|
||||
file.createNewFile()
|
||||
val fileContent = Http.get("$ASSETS_BASE_URL/files/pixiv_index_v3.json")
|
||||
file.writeText(fileContent)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/9/10
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import java.io.InputStream
|
||||
|
||||
object Resources {
|
||||
fun loadFromResources(filename: String): InputStream? {
|
||||
return this::class.java.classLoader.getResourceAsStream(filename)
|
||||
}
|
||||
|
||||
fun loadFromResourcesAsBytes(filename: String): ByteArray? {
|
||||
val inputStream = this::class.java.classLoader.getResourceAsStream(filename)
|
||||
return inputStream?.use { it.readBytes() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/10/8
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.misc
|
||||
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
|
||||
fun String.toURL(): URL {
|
||||
return URI(this).toURL()
|
||||
}
|
||||
|
||||
fun String.toURI(): URI {
|
||||
return URI(this)
|
||||
}
|
||||
Reference in New Issue
Block a user