Author SHA1 Message Date
RTAkland dff2c549dd feat: add stock data api 2024-10-01 11:50:35 +08:00
RTAkland bf9e6dd311 chore: bump rob to 1.11.8 2024-10-01 09:53:10 +08:00
RTAkland 7372724274 feat: add r18 setu api 2024-09-29 21:39:20 +08:00
RTAkland 44e3e093d1 chore: chore: chore: chore: chore: chore: chore: chore: chore: chore: chore: chore 2024-09-29 14:15:16 +08:00
RTAkland e2b6ffff38 chore: move ten setu to redeem list 2024-09-28 20:53:49 +08:00
RTAkland 042cef3340 chore: bump ronebot to 1.11.6 2024-09-28 18:03:25 +08:00
RTAkland 32c822c3a1 chore: improve rdm command 2024-09-28 16:31:55 +08:00
RTAkland 9aab28334e chore: add command description, and add command aliases 2024-09-28 14:48:11 +08:00
RTAkland 120fc38084 feat: add poke reply 2024-09-28 12:37:18 +08:00
RTAkland bc04c53517 chore: improve some command 2024-09-27 23:31:01 +08:00
RTAkland e040819e61 chore: update rob version 2024-09-27 19:36:56 +08:00
RTAkland 9762d8d566 chore: chore: chore: chore: chore: chore: chore 2024-09-27 15:22:24 +08:00
RTAkland cc30d8e1c0 chore: format code 2024-09-26 22:55:10 +08:00
RTAkland 8a31dce4d4 chore: use reply 2024-09-26 22:11:28 +08:00
RTAkland 4a2575e1c5 chore: remove command aliases 2024-09-26 22:09:04 +08:00
RTAkland 1953897642 chore: rename classes 2024-09-26 21:59:14 +08:00
RTAkland a51be7292f chore: chore 2024-09-26 21:58:17 +08:00
RTAkland 0016fa578d chore: improve niuzi bank command 2024-09-26 21:56:44 +08:00
RTAkland a6537628d5 fix: fix zibi not work 2024-09-26 21:56:16 +08:00
RTAkland ef7e3bf1ad fix: fix db bug 2024-09-26 19:16:16 +08:00
RTAkland 45a6cbece3 fix: fix no member null 2024-09-26 18:57:31 +08:00
RTAkland 3c147c9ad6 feat: add niuzi rank, and niuzi bank rank 2024-09-26 18:43:24 +08:00
RTAkland 8110ed6cd4 chore: lowercase match 2024-09-26 18:13:09 +08:00
RTAkland 862670183a feat: support query single command description 2024-09-26 17:51:01 +08:00
RTAkland 53a1807d9d chore: remove command alias 2024-09-26 17:43:13 +08:00
RTAkland 2d7d81c825 chore: rename 2024-09-26 17:42:49 +08:00
RTAkland 478c0ce4fd chore: functional programming 2024-09-26 17:41:11 +08:00
RTAkland e832b1cb3b feat: add gif ascii art generate 2024-09-26 17:38:28 +08:00
RTAkland a3058780be feat: add weekday select 2024-09-26 15:42:47 +08:00
RTAkland f332031961 feat: add gpbt command 2024-09-26 15:26:07 +08:00
RTAkland 04021a8fff fix: fix incorrect word 2024-09-26 15:06:53 +08:00
RTAkland 06d0aeb529 chore: improve help command 2024-09-26 14:01:26 +08:00
RTAkland 917d4f0d26 fix: fix mface and image ascii art generator 2024-09-26 12:33:09 +08:00
RTAkland 1b5a6c627d fix: mcping desc color code 2024-09-26 05:52:02 +08:00
RTAkland 6e38ff1b04 chore: change command names 2024-09-26 05:47:31 +08:00
RTAkland 7a6e00d4d2 chore: use kotlin's reflection 2024-09-26 05:44:47 +08:00
RTAkland cbfaf0d8aa ci: update cloc 2024-09-26 05:32:32 +08:00
RTAkland 9f0133de8a ci: add cloc 2024-09-26 05:29:35 +08:00
RTAkland 0442c0ef6a ci: add cloc 2024-09-26 05:27:03 +08:00
RTAkland 660e5bcbe8 fix: fix help command description 2024-09-26 05:21:42 +08:00
RTAkland 8dc311fb90 feat: add annotation to add command description 2024-09-26 05:20:10 +08:00
RTAkland 0a28d05bfe refactor: mcping command 2024-09-26 00:30:25 +08:00
RTAkland 9a9c767e17 chore: help sort name 2024-09-25 23:16:58 +08:00
RTAkland 1c89d54636 feat: add qq music api search 2024-09-25 23:04:49 +08:00
RTAkland ecd50ffea6 chore: add exception catch 2024-09-25 18:23:27 +08:00
RTAkland 19e980be86 chore: format code and add qodana 2024-09-25 18:18:28 +08:00
RTAkland 4d2be92081 chore: rename func 2024-09-25 18:13:03 +08:00
RTAkland 3e65d6ef3e chore: update ronebot version 2024-09-25 18:06:31 +08:00
RTAkland a2117f04a4 chore: update ronebot version 2024-09-25 16:14:57 +08:00
RTAkland a91a5f475d chore: chore 2024-09-25 16:01:15 +08:00
RTAkland 4a9483bf12 fix: fix transfer 2024-09-25 15:07:57 +08:00
RTAkland ae5f60df41 chore: format code 2024-09-25 14:48:59 +08:00
RTAkland ddad36b28d chore: update lib 2024-09-25 12:51:34 +08:00
RTAkland 7e2d2d7cdb feat: add llama command 2024-09-24 20:51:20 +08:00
RTAkland 82f4b3c542 chore: move obj 2024-09-24 20:21:30 +08:00
RTAkland 98f4f5d10f feat: add dm search 2024-09-24 19:11:04 +08:00
RTAkland 7688f538fb fix: fix withdraw 2024-09-24 15:46:22 +08:00
RTAkland 765a1a60e6 feat: add niuzi bank commands 2024-09-24 15:41:24 +08:00
RTAkland e51c7ecf04 chore: remove genshin command 2024-09-24 14:56:51 +08:00
RTAkland 57b454e7d0 feat: add failback 2024-09-24 14:55:09 +08:00
RTAkland 8fc6dd6443 feat: merge func 2024-09-24 14:46:06 +08:00
RTAkland 02578a8901 feat: add genshin command 2024-09-24 14:30:29 +08:00
RTAkland 0c19984e60 chore: format code 2024-09-24 13:35:26 +08:00
RTAkland e8b847a7ac feat: add niuzi transfer and niuzi query command 2024-09-24 13:30:08 +08:00
91 changed files with 1975 additions and 983 deletions

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
name: Count Lines of Code
on:
push:
branches:
- main
jobs:
count-loc:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Install cloc
run: sudo apt-get install -y cloc
- name: Count lines of code
id: cloc
run: |
cloc . >> $GITHUB_STEP_SUMMARY
+1
View File
@@ -39,6 +39,7 @@ dependencies {
implementation(libs.simple.java.mail) implementation(libs.simple.java.mail)
implementation(libs.jsoup) implementation(libs.jsoup)
implementation(libs.nashorn.core) implementation(libs.nashorn.core)
implementation(libs.finnhub)
} }
tasks.build { tasks.build {
+4 -2
View File
@@ -1,15 +1,16 @@
[versions] [versions]
kotlinVersion = "2.0.10" kotlinVersion = "2.0.10"
ronebotVersion = "1.10.0" ronebotVersion = "1.11.8"
shadowVersion = "8.3.0" shadowVersion = "8.3.0"
okhttpVersion = "5.0.0-alpha.14" okhttpVersion = "5.0.0-alpha.14"
exposedVersion = "0.53.0" exposedVersion = "0.53.0"
sqliteJDBCVersion = "3.46.1.0" sqliteJDBCVersion = "3.46.1.0"
motdPingerVersion = "1.0.1" motdPingerVersion = "1.1.2"
animatedGifLibVersion = "1.4" animatedGifLibVersion = "1.4"
simpleJavaMailVersion = "8.11.3" simpleJavaMailVersion = "8.11.3"
jsoupVersion = "1.18.1" jsoupVersion = "1.18.1"
nashornVersion = "15.4" nashornVersion = "15.4"
finnhubVersion = "2.0.20"
[libraries] [libraries]
rOneBot = { group = "cn.rtast", name = "ROneBot", version.ref = "ronebotVersion" } rOneBot = { group = "cn.rtast", name = "ROneBot", version.ref = "ronebotVersion" }
@@ -22,6 +23,7 @@ animated-gif-lib = { group = "com.madgag", name = "animated-gif-lib", version.re
simple-java-mail = { group = "org.simplejavamail", name = "simple-java-mail", version.ref = "simpleJavaMailVersion" } simple-java-mail = { group = "org.simplejavamail", name = "simple-java-mail", version.ref = "simpleJavaMailVersion" }
jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoupVersion" } jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoupVersion" }
nashorn-core = { group = "org.openjdk.nashorn", name = "nashorn-core", version.ref = "nashornVersion" } nashorn-core = { group = "org.openjdk.nashorn", name = "nashorn-core", version.ref = "nashornVersion" }
finnhub = { group = "io.finnhub", name = "kotlin-client", version.ref = "finnhubVersion" }
[bundles] [bundles]
+31
View File
@@ -0,0 +1,31 @@
#-------------------------------------------------------------------------------#
# Qodana analysis is configured by qodana.yaml file #
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
#-------------------------------------------------------------------------------#
version: "1.0"
#Specify inspection profile for code analysis
profile:
name: qodana.starter
#Enable inspections
#include:
# - name: <SomeEnabledInspectionId>
#Disable inspections
#exclude:
# - name: <SomeDisabledInspectionId>
# paths:
# - <path/where/not/run/inspection>
projectJDK: 17 #(Applied in CI/CD pipeline)
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
#bootstrap: sh ./prepare-qodana.sh
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
#plugins:
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
linter: jetbrains/qodana-jvm:latest
+68 -1
View File
@@ -7,11 +7,29 @@
package cn.rtast.fancybot package cn.rtast.fancybot
import cn.rtast.fancybot.commands.AboutCommand
import cn.rtast.fancybot.commands.EchoCommand
import cn.rtast.fancybot.commands.HelpCommand
import cn.rtast.fancybot.commands.StatusCommand
import cn.rtast.fancybot.commands.lookup.*
import cn.rtast.fancybot.commands.misc.*
import cn.rtast.fancybot.commands.niuzi.*
import cn.rtast.fancybot.commands.parse.AsciiArtCommand
import cn.rtast.fancybot.commands.parse.ReverseGIFCommand
import cn.rtast.fancybot.commands.misc.JrrpCommand
import cn.rtast.fancybot.commands.niuzi.NiuziRedeemCommand
import cn.rtast.fancybot.commands.misc.ShortLinkCommand
import cn.rtast.fancybot.entity.Config import cn.rtast.fancybot.entity.Config
import cn.rtast.fancybot.entity.enums.ImageType import cn.rtast.fancybot.entity.enums.ImageType
import cn.rtast.fancybot.entity.enums.WSType import cn.rtast.fancybot.entity.enums.WSType
import cn.rtast.fancybot.items.*
import cn.rtast.fancybot.util.file.ConfigManager
import cn.rtast.fancybot.util.file.NiuziBankManager
import cn.rtast.fancybot.util.file.NiuziManager
import cn.rtast.fancybot.util.item.ItemManager
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import java.time.Instant
val gson: Gson = GsonBuilder() val gson: Gson = GsonBuilder()
.setPrettyPrinting() .setPrettyPrinting()
@@ -32,11 +50,60 @@ val DEFAULT_CONFIG = Config(
imageType = ImageType.PNG, imageType = ImageType.PNG,
openAIAPIHost = "https://api.moonshot.cn", openAIAPIHost = "https://api.moonshot.cn",
openAIAPIKey = "114514", openAIAPIKey = "114514",
openAIModel = "moonshot-v1-8k",
smtpHost = "127.0.0.1", smtpHost = "127.0.0.1",
smtpPort = 25, smtpPort = 25,
smtpUser = "114514", smtpUser = "114514",
smtpPassword = "1919810", smtpPassword = "1919810",
smtpFromAddress = "fancybot@repo.rtast.cn", smtpFromAddress = "fancybot@repo.rtast.cn",
admins = listOf(3458671395L), admins = listOf(3458671395L),
enableAntiRevoke = true enableAntiRevoke = true,
llamaUrl = "http://127.0.0.1",
llamaModel = "llama3.1",
qqMusicApiUrl = "http://127.0.0.1:3200",
startUpNoticeUser = 114514L,
selfId = 114514L
)
val configManager = ConfigManager()
val itemManager = ItemManager()
val niuziManager = NiuziManager()
val niuziBankManager = NiuziBankManager()
val START_UP_TIME = Instant.now().epochSecond
val items = listOf(
HeisiItem(), BaisiItem(),
SetuItem(), NiuziItem(),
TenSetuItem(), TenSetuR18Item()
)
val commands = listOf(
EchoCommand(), JrrpCommand(),
NiuziRedeemCommand(), HitokotoCommand(),
KFCCommand(), QRCodeCommand(),
AntiRevokeCommand(), MCPingCommand(),
WeatherCommand(), CigaretteCommand(),
RemakeCommand(), PixivCommand(),
RUACommand(), NslookupCommand(),
CompilerCommand(), AICommand(),
GithubUserCommand(), AboutCommand(),
MusicPlayUrlCommand(), DomainPriceCommand(),
SendMailCommand(), ZiBiCommand(),
UnsetZiBiCommand(), WikipediaCommand(),
AsciiArtCommand(), StatusCommand(),
JueCommand(), ShortLinkCommand(),
ShotOtherCommand(), ReverseGIFCommand(),
HelpCommand(), MusicCommand(),
LikeMeCommand(), NiuziTransferCommand(),
NiuziSignCommand(), NiuziJiJianCommand(),
NiuziQueryCommand(), MyNiuziCommand(),
NiuziBankCommand(), WithdrawCommand(),
BankTransferCommand(), CreateBankAccountCommand(),
BankBalanceCommand(), DepositCommand(),
DMSearchCommand(), LlamaCommand(),
QQMusicCommand(), BullShitGenerateCommand(),
NiuziRankCommand(), NiuziBankRankCommand(),
ShotSelfCommand(), TenSetuCommand(),
StockDataCommand()
) )
+41 -109
View File
@@ -7,42 +7,13 @@
package cn.rtast.fancybot package cn.rtast.fancybot
import cn.rtast.fancybot.commands.AboutCommand import cn.rtast.fancybot.commands.parse.*
import cn.rtast.fancybot.commands.EchoCommand
import cn.rtast.fancybot.commands.HelpCommand
import cn.rtast.fancybot.commands.StatusCommand
import cn.rtast.fancybot.commands.lookup.*
import cn.rtast.fancybot.commands.misc.*
import cn.rtast.fancybot.commands.parse.AsciiArtCommand
import cn.rtast.fancybot.commands.parse.BVParseCommand
import cn.rtast.fancybot.commands.parse.CalculateCommand
import cn.rtast.fancybot.commands.parse.GitHubParseCommand
import cn.rtast.fancybot.commands.parse.ImageURLCommand
import cn.rtast.fancybot.commands.parse.ReverseGIFCommand
import cn.rtast.fancybot.commands.record.JiJianCommand
import cn.rtast.fancybot.commands.record.JrrpCommand
import cn.rtast.fancybot.commands.record.MyNiuziCommand
import cn.rtast.fancybot.commands.record.MyPointCommand
import cn.rtast.fancybot.commands.record.NiuziSignCommand
import cn.rtast.fancybot.commands.record.RedeemCommand
import cn.rtast.fancybot.commands.record.ShortLinkCommand
import cn.rtast.fancybot.commands.record.SignCommand
import cn.rtast.fancybot.entity.bili.CardShare
import cn.rtast.fancybot.entity.enums.WSType import cn.rtast.fancybot.entity.enums.WSType
import cn.rtast.fancybot.items.BaisiItem
import cn.rtast.fancybot.items.HeisiItem
import cn.rtast.fancybot.items.SetuItem
import cn.rtast.fancybot.util.file.ConfigManager
import cn.rtast.fancybot.util.file.NiuziManager
import cn.rtast.fancybot.util.file.SignManager
import cn.rtast.fancybot.util.initDatabase import cn.rtast.fancybot.util.initDatabase
import cn.rtast.fancybot.util.item.ItemManager
import cn.rtast.fancybot.util.str.fromJson
import cn.rtast.rob.ROneBotFactory import cn.rtast.rob.ROneBotFactory
import cn.rtast.rob.entity.AddFriendRequest import cn.rtast.rob.entity.*
import cn.rtast.rob.entity.FileEvent import cn.rtast.rob.entity.lagrange.FileEvent
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.lagrange.PokeEvent
import cn.rtast.rob.entity.GroupRevokeMessage
import cn.rtast.rob.enums.ArrayMessageType import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@@ -51,14 +22,13 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
import java.net.URI import java.net.URI
import java.time.Instant
class FancyBot : OneBotListener { class FancyBot : OneBotListener {
private val coroutineScope = CoroutineScope(Dispatchers.IO) private val coroutineScope = CoroutineScope(Dispatchers.IO)
override suspend fun onWebsocketOpenEvent() { override suspend fun onWebsocketOpenEvent() {
this.broadcastMessage("FancyBot启动成功了呢~") this.sendPrivateMessage(configManager.startUpNoticeUser, "FancyBot启动成~")
} }
override suspend fun onGroupMessage(message: GroupMessage, json: String) { override suspend fun onGroupMessage(message: GroupMessage, json: String) {
@@ -69,13 +39,22 @@ class FancyBot : OneBotListener {
val messageId = message.messageId val messageId = message.messageId
println("$sender($senderId: $groupId >>> $messageId): $msg") println("$sender($senderId: $groupId >>> $messageId): $msg")
if (message.message.any { it.type == ArrayMessageType.face && it.data.id.toString() == "419" }) {
message.reply("你发牛魔的火车呢, 我直接就是打断")
}
if (message.rawMessage.contains("原神")) {
message.reply("你原神牛魔呢")
}
ReverseGIFCommand.callback(message)
AsciiArtCommand.callback(message)
if (message.rawMessage.toList().any { it in arrayListOf('*', '-', '/', '+', '=') }) { if (message.rawMessage.toList().any { it in arrayListOf('*', '-', '/', '+', '=') }) {
val calculateResult = CalculateCommand.parse(message.rawMessage) val calculateResult = CalculateCommand.parse(message.rawMessage)
calculateResult?.let { message.reply(calculateResult) } calculateResult?.let { message.reply(calculateResult) }
} }
ReverseGIFCommand.callback(message)
AsciiArtCommand.callback(message)
if (message.message.any { it.type == ArrayMessageType.reply }) { // Image url parse if (message.message.any { it.type == ArrayMessageType.reply }) { // Image url parse
val command = message.message.reversed().find { it.type == ArrayMessageType.text }!!.data.text!! val command = message.message.reversed().find { it.type == ArrayMessageType.text }!!.data.text!!
val replyId = message.message.find { it.type == ArrayMessageType.reply }!!.data.id!! val replyId = message.message.find { it.type == ArrayMessageType.reply }!!.data.id!!
@@ -85,6 +64,18 @@ class FancyBot : OneBotListener {
} }
} }
if (message.rawMessage.startsWith("https://github.com/") || message.rawMessage.startsWith("git@github.com:")) {
GitHubParseCommand.parse(this, message)
}
if (message.rawMessage.startsWith("BV") ||
message.rawMessage.startsWith("https://www.bilibili.com") ||
message.rawMessage.contains("https://b23.tv/") ||
message.message.find { it.type == ArrayMessageType.json } != null
) {
BVParseCommand.parse(this, message)
}
coroutineScope.launch { coroutineScope.launch {
message.message.forEach { message.message.forEach {
if (it.type == ArrayMessageType.image) { if (it.type == ArrayMessageType.image) {
@@ -97,40 +88,6 @@ class FancyBot : OneBotListener {
} }
} }
} }
if (message.rawMessage.startsWith("https://github.com/") || message.rawMessage.startsWith("git@github.com:")) {
GitHubParseCommand.parse(this, message)
}
if (message.rawMessage.startsWith("BV") ||
message.rawMessage.startsWith("https://www.bilibili.com") ||
message.rawMessage.contains("https://b23.tv/") ||
message.message.find { it.type == ArrayMessageType.json } != null
) {
// parse bilibili video with a link, bvid or b23.tv link
val bvid = if (message.rawMessage.startsWith("BV")) {
message.rawMessage
} else if (message.rawMessage.split(" ").last().startsWith("https://b23.tv/")) {
val shortUrl = message.rawMessage.split(" ").last()
BVParseCommand.getShortUrlBVID(shortUrl)
} else if (message.message.find { it.type == ArrayMessageType.json } != null) {
val card = message.message.find { it.type == ArrayMessageType.json }!!
.data.data!!.toString().fromJson<CardShare>()
val shortUrl = if (card.meta.detail == null) {
if (!card.meta.news?.tag!!.contains("哔哩哔哩")) return
card.meta.news.jumpUrl
} else {
if (!card.meta.detail.title.contains("哔哩哔哩")) return
card.meta.detail.qqDocUrl
}
BVParseCommand.getShortUrlBVID(shortUrl)
} else {
message.rawMessage.split("?").first()
.split("/")
.last { it.isNotEmpty() && it.isNotBlank() }
}
BVParseCommand.parse(this, bvid, message)
}
} }
override suspend fun onGroupMessageRevoke(message: GroupRevokeMessage) { override suspend fun onGroupMessageRevoke(message: GroupRevokeMessage) {
@@ -157,7 +114,7 @@ class FancyBot : OneBotListener {
override suspend fun onLeaveEvent(groupId: Long, userId: Long, operator: Long, time: Long) { override suspend fun onLeaveEvent(groupId: Long, userId: Long, operator: Long, time: Long) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addText("有人退群了") .addText("有人坐飞船离开了本星系~")
.addNewLine() .addNewLine()
.addText("QQ: $userId | 操作者: ${if (operator == 0L) "主动退出" else operator}") .addText("QQ: $userId | 操作者: ${if (operator == 0L) "主动退出" else operator}")
.addNewLine() .addNewLine()
@@ -165,45 +122,20 @@ class FancyBot : OneBotListener {
.build() .build()
this.sendGroupMessage(groupId, msg) this.sendGroupMessage(groupId, msg)
} }
override suspend fun onPoke(event: PokeEvent) {
event.groupId?.let {
if (event.targetId == configManager.selfId) {
val msg = MessageChain.Builder()
.addAt(event.userId)
.addText("${event.action.first()}牛魔呢")
.build()
this.sendGroupMessage(it, msg)
}
}
}
} }
val configManager = ConfigManager()
val itemManager = ItemManager()
val signManager = SignManager()
val niuziManager = NiuziManager()
val items = listOf(
HeisiItem(),
BaisiItem(),
SetuItem()
)
val commands = listOf(
EchoCommand(), JrrpCommand(),
MusicCommand(), SignCommand(),
RedeemCommand(), MyPointCommand(),
HitokotoCommand(), FKXQSCommand(),
QRCodeCommand(), AntiRevokeCommand(),
MCPingCommand(), HelpCommand(),
WeatherCommand(), CigaretteCommand(),
RemakeCommand(), PixivCommand(),
RUACommand(), NslookupCommand(),
NiuziSignCommand(), MyNiuziCommand(),
JiJianCommand(), LikeMeCommand(),
CompilerCommand(), AICommand(),
GithubUserCommand(), AboutCommand(),
MusicPlayUrlCommand(), DomainPriceCommand(),
SendMailCommand(), ZiBiCommand(),
UnsetZiBiCommand(), WikipediaCommand(),
AsciiArtCommand(), StatusCommand(),
JueCommand(), ShortLinkCommand(),
TenSetuCommand(), ShotSelfCommand(),
ShotOtherCommand(), ReverseGIFCommand(),
DMCommand()
)
val START_UP_TIME = Instant.now().epochSecond
fun initFilesDir() { fun initFilesDir() {
File("./files/images").also { it.mkdirs() } File("./files/images").also { it.mkdirs() }
} }
@@ -0,0 +1,12 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/26
*/
package cn.rtast.fancybot.annotations
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class CommandDescription(val description: String)
@@ -7,18 +7,18 @@
package cn.rtast.fancybot.commands package cn.rtast.fancybot.commands
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("关于")
class AboutCommand : BaseCommand() { class AboutCommand : BaseCommand() {
override val commandNames = listOf("/about", "/关于") override val commandNames = listOf("/about", "/关于")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addNewLine()
.addText("Bot名称: FancyBot") .addText("Bot名称: FancyBot")
.addNewLine() .addNewLine()
.addText("作者: RTAkland") .addText("作者: RTAkland")
@@ -27,6 +27,6 @@ class AboutCommand : BaseCommand() {
.addNewLine() .addNewLine()
.addText("项目地址: https://repo.rtast.cn/RTAkland/FancyBot") .addText("项目地址: https://repo.rtast.cn/RTAkland/FancyBot")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
} }
} }
@@ -7,10 +7,12 @@
package cn.rtast.fancybot.commands package cn.rtast.fancybot.commands
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("Echo")
class EchoCommand : BaseCommand() { class EchoCommand : BaseCommand() {
override val commandNames = listOf("/echo") override val commandNames = listOf("/echo")
@@ -7,24 +7,54 @@
package cn.rtast.fancybot.commands package cn.rtast.fancybot.commands
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.commands import cn.rtast.fancybot.commands
import cn.rtast.fancybot.configManager
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.hasAnnotation
@CommandDescription("帮助")
class HelpCommand : BaseCommand() { class HelpCommand : BaseCommand() {
override val commandNames = listOf("/help", "/帮助") override val commandNames = listOf("/help", "/帮助")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val allCommands = commands.joinToString("\n") { if (args.isEmpty()) {
"[${it.javaClass.name.split(".").last().replace("Command", "")}] 命令:${it.commandNames.joinToString(",")}" val node = NodeMessageChain.Builder()
val msg = MessageChain.Builder()
commands.sortedBy { it::class.simpleName }.forEach {
val description = if (!it::class.hasAnnotation<CommandDescription>()) "暂无描述"
else it::class.findAnnotation<CommandDescription>()?.description!!
val commandName = it::class.simpleName?.replace("Command", "")!!
val commandNames = it.commandNames.joinToString(",")
msg.addText("[$commandName] [$description] 命令: $commandNames")
.addNewLine()
}
msg.addText("共计${commands.size}条命令")
node.addMessageChain(msg.build(), configManager.selfId)
message.reply(node.build())
} else {
val commandName = args.first().replace("/", "")
val matchedCommand = commands.find {
it.commandNames.map { map -> map.replace("/", "").lowercase() }.contains(commandName)
}
if (matchedCommand == null) {
message.reply("未查询到该命令")
return
}
val description = matchedCommand::class.findAnnotation<CommandDescription>()?.description ?: "暂无描述"
val msg = MessageChain.Builder()
.addText("类名: ${matchedCommand::class.simpleName}")
.addNewLine()
.addText("指令: ${matchedCommand.commandNames.joinToString(",")}")
.addNewLine()
.addText("描述: $description")
.build()
message.reply(msg)
} }
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addNewLine()
.addText(allCommands)
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
@@ -8,12 +8,14 @@
package cn.rtast.fancybot.commands package cn.rtast.fancybot.commands
import cn.rtast.fancybot.START_UP_TIME import cn.rtast.fancybot.START_UP_TIME
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.time.Instant import java.time.Instant
@CommandDescription("状态")
class StatusCommand : BaseCommand() { class StatusCommand : BaseCommand() {
override val commandNames = listOf("/status") override val commandNames = listOf("/status")
@@ -7,31 +7,36 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.gpt.ChatCompletionsPayload import cn.rtast.fancybot.entity.gpt.ChatCompletionsPayload
import cn.rtast.fancybot.entity.gpt.ChatCompletionsResponse import cn.rtast.fancybot.entity.gpt.ChatCompletionsResponse
import cn.rtast.fancybot.entity.gpt.LlamaResponse
import cn.rtast.fancybot.entity.gpt.ModelList import cn.rtast.fancybot.entity.gpt.ModelList
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.toJson import cn.rtast.fancybot.util.str.toJson
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("问AI(GPT)")
class AICommand : BaseCommand() { class AICommand : BaseCommand() {
override val commandNames = listOf("/ai", "问AI") override val commandNames = listOf("/ai")
private val openAIModel = configManager.openAIModel
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("发送`/ai [模型] <问题>`即可询问AI哦~") .addText("发送`/ai [模型] <问题>`即可询问AI哦~")
.addNewLine() .addNewLine()
.addText("不指定模型默认为`moonshot-v1-8k`") .addText("不指定模型默认为从配置文件中读取 >>>${openAIModel}")
.addNewLine() .addNewLine()
.addText("发送`/ai list`可以获取可用的模型列表~") .addText("发送`/ai list`可以获取可用的模型列表~")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
return return
} }
@@ -42,27 +47,52 @@ class AICommand : BaseCommand() {
) )
val modelsString = models.data.joinToString(", ") { it.id } val modelsString = models.data.joinToString(", ") { it.id }
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addReply(message.messageId)
.addText("可用的模型列表如下: ") .addText("可用的模型列表如下: ")
.addNewLine() .addNewLine()
.addText(modelsString) .addText(modelsString)
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
return return
} }
val model = if (args.size == 1) "moonshot-v1-8k" else args.first() val model = if (args.size == 1) openAIModel else args.first()
val content = if (args.size == 1) args.joinToString(" ") else args.drop(1).joinToString(" ") val content = if (args.size == 1) args.joinToString(" ") else args.drop(1).joinToString(" ")
val messages = ChatCompletionsPayload(model, listOf(ChatCompletionsPayload.Message(content))) val messages = ChatCompletionsPayload(model, listOf(ChatCompletionsPayload.Message(content)))
val response = Http.post<ChatCompletionsResponse>( val response = Http.post<ChatCompletionsResponse>(
"${configManager.openAIAPIHost}/v1/chat/completions", "${configManager.openAIAPIHost}/v1/chat/completions", messages.toJson(),
messages.toJson(),
mapOf("Authorization" to "Bearer ${configManager.openAIAPIKey}") mapOf("Authorization" to "Bearer ${configManager.openAIAPIKey}")
) )
val nodeMsg = NodeMessageChain.Builder()
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addReply(message.messageId)
.addText(response.choices.first().message.content) .addText(response.choices.first().message.content)
.build() .build()
listener.sendGroupMessage(message.groupId, msg) nodeMsg.addMessageChain(msg, configManager.selfId)
listener.sendGroupForwardMsg(message.groupId, nodeMsg.build())
}
}
@CommandDescription("问AI(LLAMA)")
class LlamaCommand : BaseCommand() {
override val commandNames = listOf("/llama")
private val llamaURL = configManager.llamaUrl
private val llamaModel = configManager.llamaModel
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
message.reply("发送`/llama <问题>`即可使用llama模型来回复")
return
}
val prompt = args.joinToString(" ")
val payload = ChatCompletionsPayload(llamaModel, listOf(ChatCompletionsPayload.Message(prompt)))
val response = Http.post<LlamaResponse>("$llamaURL/api/chat", payload.toJson())
val nodeMsg = NodeMessageChain.Builder()
val msg = MessageChain.Builder()
.addText("AI回复如下:")
.addNewLine()
.addText(response.message.content)
.build()
nodeMsg.addMessageChain(msg, configManager.selfId)
listener.sendGroupForwardMsg(message.groupId, nodeMsg.build())
} }
} }
@@ -7,32 +7,32 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.cigarette.Cigarette import cn.rtast.fancybot.entity.cigarette.Cigarette
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.segment.Node
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.net.URI import java.net.URI
@CommandDescription("查询香烟价格")
class CigaretteCommand : BaseCommand() { class CigaretteCommand : BaseCommand() {
override val commandNames = listOf("/香烟", "/tobacco", "/cigarette") override val commandNames = listOf("/tobacco")
private val apiUrl = "https://www.yanyue.cn/api/rc/product/yanlist" private val apiUrl = "https://www.yanyue.cn/api/rc/product/yanlist"
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addNewLine()
.addText("发送/tobacco <名称> [数量] 来搜索结果哦~") .addText("发送/tobacco <名称> [数量] 来搜索结果哦~")
.addNewLine() .addNewLine()
.addText("最多只能显示出10条结果哦, 不指定数量的话默认是3条~") .addText("最多只能显示出10条结果哦, 不指定数量的话默认是3条~")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
return return
} }
val limit = if (args.size == 1) 3 else if (args.last().toInt() > 10) 3 else args.last().toInt() val limit = if (args.size == 1) 3 else if (args.last().toInt() > 10) 3 else args.last().toInt()
@@ -42,8 +42,7 @@ class CigaretteCommand : BaseCommand() {
val headerMsg = MessageChain.Builder() val headerMsg = MessageChain.Builder()
.addText("搜索到${result.totalCount}条结果, 仅展示前 $limit 条结果哦~") .addText("搜索到${result.totalCount}条结果, 仅展示前 $limit 条结果哦~")
.build() .build()
val headerNode = Node(Node.Data("", message.userId.toString(), headerMsg.finalArrayMsgList)) nodeMsg.addMessageChain(headerMsg, message.sender.userId)
nodeMsg.addNode(headerNode)
result.productList.asSequence().take(limit).forEach { result.productList.asSequence().take(limit).forEach {
val imageBase64 = URI(it.cover).toURL().readBytes().encodeToBase64() val imageBase64 = URI(it.cover).toURL().readBytes().encodeToBase64()
val tempMsg = MessageChain.Builder() val tempMsg = MessageChain.Builder()
@@ -55,14 +54,13 @@ class CigaretteCommand : BaseCommand() {
.addText("参考价: 单盒: ${it.packPrice}元 | 整条: ${it.barPrice}") .addText("参考价: 单盒: ${it.packPrice}元 | 整条: ${it.barPrice}")
.addNewLine() .addNewLine()
.build() .build()
val tempNode = Node(Node.Data("", message.userId.toString(), tempMsg.finalArrayMsgList)) nodeMsg.addMessageChain(tempMsg, configManager.selfId)
nodeMsg.addNode(tempNode)
} }
val footerMsg = MessageChain.Builder() val footerMsg = MessageChain.Builder()
.addText("吸烟有害健康, 尽早戒烟有益健康。") .addText("吸烟有害健康, 尽早戒烟有益健康。")
.build() .build()
val footerNode = Node(Node.Data("", message.userId.toString(), footerMsg.finalArrayMsgList)) nodeMsg.addMessageChain(footerMsg, configManager.selfId)
nodeMsg.addNode(footerNode) message.reply(nodeMsg.build())
listener.sendGroupForwardMsg(message.groupId, nodeMsg.build()) message.sender.groupPoke()
} }
} }
@@ -1,49 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.entity.bili.Search
import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.parseTimeStamp
import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.str.extractPlainTextFromHtml
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener
import java.net.URI
class DMCommand : BaseCommand() {
override val commandNames = listOf("/dm")
private val searchAPIUrl = "https://api.bilibili.com/x/web-interface/wbi/search/all/v2"
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val keyword = args.first()
val response = Http.get<Search>(
searchAPIUrl, mapOf("keyword" to keyword),
).data.result.find { it.resultType == "media_bangumi" }!!
.data.first()
val nodeMsg = NodeMessageChain.Builder()
val msg = MessageChain.Builder()
val imageBase64 = URI(response.cover).toURL().readBytes().encodeToBase64()
msg.addImage(imageBase64, true)
.addText("番名: ${response.title.extractPlainTextFromHtml()}(${response.orgTitle})")
.addNewLine()
.addText(response.styles)
.addNewLine()
.addText("${response.areas} · ${response.pubTime.parseTimeStamp().year} · ${response.indexShow}")
.addNewLine()
.addText(response.desc)
.addNewLine()
.addText(response.url)
nodeMsg.addMessageChain(msg.build(), message.sender.userId)
listener.sendGroupForwardMsg(message.groupId, nodeMsg.build())
}
}
@@ -0,0 +1,66 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.bgm.BGMSearch
import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener
import okhttp3.OkHttpClient
import okhttp3.Request
@CommandDescription("搜索动漫")
class DMSearchCommand : BaseCommand() {
override val commandNames = listOf("/dm", "动漫")
private val client = OkHttpClient()
companion object {
private const val API_URL = "https://api.bgm.tv/search/subject/#{}?type=2&responseGroup=small"
}
private fun followRedirect(url: String): ByteArray {
val request = Request.Builder().url(url).build()
client.newCall(request).execute().use { response ->
return response.body.bytes()
}
}
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
message.reply("发送`/dm <关键词>`即可搜索番剧啦~")
return
}
try {
val keyword = args.joinToString(" ")
val response = Http.get<BGMSearch>(API_URL.replace("#{}", keyword)).list
val nodeMsg = NodeMessageChain.Builder()
response.asSequence().take(5).forEach {
val imageBase64 = this.followRedirect(it.images.large).encodeToBase64()
val tempMsg = MessageChain.Builder()
.addImage(imageBase64, true)
.addText("${it.name} | ${it.nameCN}")
.addNewLine()
.addText(it.url)
.build()
nodeMsg.addMessageChain(tempMsg, configManager.selfId)
}
val footerNode = MessageChain.Builder().addText("数据来源: Bangumi").build()
nodeMsg.addMessageChain(footerNode, configManager.selfId)
listener.sendGroupForwardMsg(message.groupId, nodeMsg.build())
} catch (_: Exception) {
message.reply("没有搜索到结果呢~")
}
}
}
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.domain.PricePayload import cn.rtast.fancybot.entity.domain.PricePayload
import cn.rtast.fancybot.entity.domain.PriceResponse import cn.rtast.fancybot.entity.domain.PriceResponse
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
@@ -21,8 +22,9 @@ import java.awt.Color
import java.awt.Font import java.awt.Font
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
@CommandDescription("查询域名价格")
class DomainPriceCommand : BaseCommand() { class DomainPriceCommand : BaseCommand() {
override val commandNames = listOf("/domain") override val commandNames = listOf("/domain", "/dp")
private val canvasWidth = 400 private val canvasWidth = 400
private val canvasHeight = 300 private val canvasHeight = 300
@@ -67,7 +69,7 @@ class DomainPriceCommand : BaseCommand() {
g2d.color = textColor g2d.color = textColor
g2d.drawString("域名$domain${if (available) "可以注册" else "已被注册"}", 50, 110) g2d.drawString("域名$domain${if (available) "可以注册" else "已被注册"}", 50, 110)
g2d.drawString("${if (premium) "是" else "不是"}白金域名", 50, 140) g2d.drawString("${if (premium) "是" else "不是"}白金域名", 50, 140)
g2d.drawString("首年注册价格: ${domainPrice.first}", 50, 170) g2d.drawString("首年注册价格: ${domainPrice.first}", 50, 170)
g2d.drawString("续费价格: ${domainPrice.second}", 50, 200) g2d.drawString("续费价格: ${domainPrice.second}", 50, 200)
g2d.drawString("数据来源: 腾讯云", 50, 230) g2d.drawString("数据来源: 腾讯云", 50, 230)
g2d.dispose() g2d.dispose()
@@ -78,10 +80,9 @@ class DomainPriceCommand : BaseCommand() {
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("发送`/domain <域名>`即可查询对应的注册和续费价格~") .addText("发送`/domain <域名>`即可查询对应的注册和续费价格~")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
return return
} }
val suffix = args.first() val suffix = args.first()
@@ -101,10 +102,7 @@ class DomainPriceCommand : BaseCommand() {
} else { } else {
this.createDomainPriceCard(suffix, response.realPrice to response.price) this.createDomainPriceCard(suffix, response.realPrice to response.price)
} }
val msg = MessageChain.Builder() val msg = MessageChain.Builder().addImage(cardImage, true).build()
.addAt(message.sender.userId) message.reply(msg)
.addImage(cardImage, true)
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.github.UserInfo import cn.rtast.fancybot.entity.github.UserInfo
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
@@ -24,8 +25,9 @@ import java.awt.Font
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.net.URI import java.net.URI
@CommandDescription("获取Github用户信息")
class GithubUserCommand : BaseCommand() { class GithubUserCommand : BaseCommand() {
override val commandNames = listOf("/gh", "/github", "gh") override val commandNames = listOf("/gh")
private val userInfoUrl = "https://api.github.com/users" private val userInfoUrl = "https://api.github.com/users"
private val backgroundColor = Color(255, 255, 240) private val backgroundColor = Color(255, 255, 240)
@@ -67,11 +69,8 @@ class GithubUserCommand : BaseCommand() {
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder().addText("发送`gh <用户名>`即可查询用户的信息~").build()
.addAt(message.sender.userId) message.reply(msg)
.addText("发送`gh <用户名>`即可查询用户的信息~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return return
} }
val username = args.first() val username = args.first()
@@ -80,10 +79,7 @@ class GithubUserCommand : BaseCommand() {
headers = mapOf("Authorization" to configManager.githubKey) headers = mapOf("Authorization" to configManager.githubKey)
) )
val image = this.createUserInfoCard(userInfo) val image = this.createUserInfoCard(userInfo)
val msg = MessageChain.Builder() val msg = MessageChain.Builder().addImage(image, true).build()
.addReply(message.messageId) message.reply(msg)
.addImage(image, true)
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
@@ -7,60 +7,86 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.entity.MCPing import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.util.str.fromJson import cn.rtast.motdpinger.BedrockPing
import cn.rtast.motdpinger.MotdPinger import cn.rtast.motdpinger.JavaPing
import cn.rtast.motdpinger.removeColorCodes
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.net.SocketException
@CommandDescription("PingMC服务器")
class MCPingCommand : BaseCommand() { class MCPingCommand : BaseCommand() {
override val commandNames = listOf("/mcping", "/mcPing") override val commandNames = listOf("/mcping")
private val pingInstance = MotdPinger()
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addText("使用方法: /mcping <host>:[port] [java|be]")
.addNewLine() .addNewLine()
.addText("使用方法: /mcping <host>:[port]") .addText("不添加平台默认Java版~")
.addNewLine()
.addText("仅限Java版服务器哦~")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
return return
} }
val parts = args.first().split(":") val platform = if (args.size == 2) args.last() else "java"
val host: String when (platform) {
val port: Int "java", "je", "Java", "JAVA" -> {
if (parts.size == 2) { val parts = args.first().split(":")
host = parts[0] val port = if (parts.size == 1) {
port = parts[1].toIntOrNull() ?: 25565 25565
} else { } else {
host = args.first() parts.last().toInt()
port = 25565 }
} val host = parts.first()
try { val response = JavaPing().ping(host, port, 10000)
val rawResponse = pingInstance.pingServer(host, port) if (response == null) {
val jsonResponse = rawResponse?.fromJson<MCPing>()!! message.reply("无法获取服务器的消息请检查输入是否正确 >>> $host:$port")
val msg = MessageChain.Builder().addAt(message.sender.userId).addNewLine() return
if (jsonResponse.favicon != null) msg.addImage(jsonResponse.favicon, true) }
msg.addText("服务器地址: $host:$port") val msg = MessageChain.Builder()
msg.addNewLine() response.favicon?.let {
msg.addText("协议版本号: ${jsonResponse.version.protocol}/${jsonResponse.version.name}") msg.addImage(response.favicon!!.replace("data:image/png;base64,", ""), true)
msg.addNewLine() }
msg.addText("玩家: ${jsonResponse.players.online}/${jsonResponse.players.max}") msg.addText("服务器地址: $host:$port | 服务器类型: Java")
listener.sendGroupMessage(message.groupId, msg.build()) .addNewLine()
} catch (_: Exception) { .addText("服务器版本: ${response.version.name}/${response.version.protocol}")
val msg = MessageChain.Builder() .addNewLine()
.addAt(message.sender.userId) .addText("在线玩家数: ${response.players.online}/${response.players.max}")
.addText("ping失败~") message.reply(msg.build())
.addNewLine() }
.addText("检查一下地址或者端口是否正确吧~")
.build() "be", "bedrock", "BE", "Bedrock" -> {
listener.sendGroupMessage(message.groupId, msg) val parts = args.first().split(":")
val port = if (parts.size == 1) {
19132
} else {
parts.last().toInt()
}
val host = parts.first()
try {
val response = BedrockPing().ping(host, port, 10000)
val msg = MessageChain.Builder()
.addText("服务器地址: $host:$port | 服务器类型: Bedrock")
.addNewLine()
.addText("服务器版本: ${response.version}/${response.protocolVersion}")
.addNewLine()
.addText("在线玩家: ${response.onlinePlayers}/${response.maxPlayers}")
.addNewLine()
.addText("MOTD: ${response.motd.removeColorCodes()}")
.addNewLine()
.addText(response.subTitle.removeColorCodes())
message.reply(msg.build())
} catch (_: SocketException) {
message.reply("无法从服务器接收Ping结果请检查服务器地址是否正确 >>> $host:$port")
}
}
else -> {
message.reply("输入错误请在 `java` 和 `be`中选择 >>> $platform")
}
} }
} }
} }
@@ -7,10 +7,12 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.music.Search import cn.rtast.fancybot.entity.music.Search
import cn.rtast.fancybot.entity.music.SearchedResult import cn.rtast.fancybot.entity.music.SearchedResult
import cn.rtast.fancybot.entity.music.SongUrl import cn.rtast.fancybot.entity.music.SongUrl
import cn.rtast.fancybot.entity.music.qq.QQMSearch
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.MusicShareType import cn.rtast.rob.enums.MusicShareType
@@ -19,15 +21,18 @@ import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.time.Instant import java.time.Instant
@CommandDescription("网易云音乐点歌")
class MusicCommand : BaseCommand() { class MusicCommand : BaseCommand() {
override val commandNames = listOf("/music", "/点歌", "点歌") override val commandNames = listOf("点歌", "music")
private val searchedResult = mutableMapOf<Long, List<SearchedResult>>() private val searchedResult = mutableMapOf<Long, List<SearchedResult>>()
companion object { companion object {
private val MUSIC_API_URL = configManager.ncmAPI
fun searchSong(keyword: String): Search { fun searchSong(keyword: String): Search {
return Http.get<Search>( return Http.get<Search>(
"${configManager.ncmAPI}/search", "$MUSIC_API_URL/search",
mapOf("keywords" to keyword), mapOf("keywords" to keyword),
) )
} }
@@ -35,11 +40,7 @@ class MusicCommand : BaseCommand() {
private suspend fun legacyMusicCommand(listener: OneBotListener, message: GroupMessage, args: List<String>) { private suspend fun legacyMusicCommand(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() message.reply("发送`/点歌` <关键词> 来搜索音乐~")
.addAt(message.sender.userId)
.addText("发送`/点歌`或者`/music` <关键词> 来搜索音乐~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return return
} }
searchedResult.forEach { (key, results) -> searchedResult.forEach { (key, results) ->
@@ -64,11 +65,7 @@ class MusicCommand : BaseCommand() {
.build() .build()
listener.sendGroupMessage(message.groupId, msg) listener.sendGroupMessage(message.groupId, msg)
} catch (_: Exception) { } catch (_: Exception) {
val msg = MessageChain.Builder() message.reply("输入有误请重新搜索本次搜索结果已清除")
.addAt(message.sender.userId)
.addText("输入有误请重新搜索本次搜索结果已清除")
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
searchedResult.remove(message.sender.userId) searchedResult.remove(message.sender.userId)
} }
@@ -76,11 +73,7 @@ class MusicCommand : BaseCommand() {
else -> { else -> {
if (searchedResult.containsKey(message.sender.userId)) { if (searchedResult.containsKey(message.sender.userId)) {
searchedResult.remove(message.sender.userId) searchedResult.remove(message.sender.userId)
val msg = MessageChain.Builder() message.reply("你上次的搜索结果还没用呢, 已经帮你把上次的搜索结果清除掉啦~")
.addAt(message.sender.userId)
.addText("你上次的搜索结果还没用呢, 已经帮你把上次的搜索结果清除掉啦~")
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
val keyword = args.joinToString(" ") val keyword = args.joinToString(" ")
val result = searchSong(keyword) val result = searchSong(keyword)
@@ -95,11 +88,7 @@ class MusicCommand : BaseCommand() {
stringResult.append("| $index | 《${searchedResult.name}》-- ${searchedResult.artists}\n") stringResult.append("| $index | 《${searchedResult.name}》-- ${searchedResult.artists}\n")
} }
stringResult.append("输入/music p <序号> 播放\n你有30秒的时间进行操作") stringResult.append("输入/music p <序号> 播放\n你有30秒的时间进行操作")
val msg = MessageChain.Builder() message.reply(stringResult.toString())
.addAt(message.sender.userId)
.addText(stringResult.toString())
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
} }
@@ -111,7 +100,7 @@ class MusicCommand : BaseCommand() {
} }
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addReply(message.messageId)
.addText("发送`点歌 <歌名>`即可点第一首搜索到的歌曲~") .addText("发送`点歌 <歌名>`即可点第一首搜索到的歌曲~")
.addNewLine() .addNewLine()
.addText("发送`点歌 <歌名> [l|legacy]`即可使用旧版点歌系统") .addText("发送`点歌 <歌名> [l|legacy]`即可使用旧版点歌系统")
@@ -121,7 +110,7 @@ class MusicCommand : BaseCommand() {
} }
val keyword = args.joinToString(" ") val keyword = args.joinToString(" ")
val result = searchSong(keyword).result.songs.asSequence().first().id val result = searchSong(keyword).result.songs.first().id
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addMusicShare(MusicShareType.Netease, result.toString()) .addMusicShare(MusicShareType.Netease, result.toString())
.build() .build()
@@ -129,11 +118,14 @@ class MusicCommand : BaseCommand() {
} }
} }
@CommandDescription("获取网易云音乐链接")
class MusicPlayUrlCommand : BaseCommand() { class MusicPlayUrlCommand : BaseCommand() {
override val commandNames = listOf("/lj", "lj", "song", "/song") override val commandNames = listOf("lj")
private val musicApiUrl = configManager.ncmAPI
private fun getPlayUrl(id: String): String { private fun getPlayUrl(id: String): String {
return Http.get<SongUrl>("${configManager.ncmAPI}/song/url", mapOf("id" to id)).data.first().url return Http.get<SongUrl>("$musicApiUrl/song/url", mapOf("id" to id)).data.first().url
} }
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
@@ -152,3 +144,24 @@ class MusicPlayUrlCommand : BaseCommand() {
listener.sendGroupMessage(message.groupId, msg) listener.sendGroupMessage(message.groupId, msg)
} }
} }
@CommandDescription("QQ音乐点歌")
class QQMusicCommand : BaseCommand() {
override val commandNames = listOf("qm", "/qm")
private val qqMusicApiUrl = configManager.qqMusicApiUrl
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
message.reply("发送`/qm <关键词>`即可搜索qq音乐的音乐哦")
return
}
val keyword = args.joinToString(" ")
val response = Http.get<QQMSearch>(
"$qqMusicApiUrl/getSearchByKey",
mapOf("key" to keyword)
).response.data.song.list.first().songId
val msg = MessageChain.Builder().addMusicShare(MusicShareType.QQ, response.toString()).build()
listener.sendGroupMessage(message.groupId, msg)
}
}
@@ -7,21 +7,32 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.InetAddress import java.net.InetAddress
import java.net.UnknownHostException
@CommandDescription("解析域名获取IP地址")
class NslookupCommand : BaseCommand() { class NslookupCommand : BaseCommand() {
override val commandNames = listOf("/nslookup", "/ns") override val commandNames = listOf("/ns")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val msg = MessageChain.Builder() val host = args.joinToString(" ")
.addReply(message.messageId) try {
.addText("域名: ${args.first()}解析后的IP地址为: ") val msg = MessageChain.Builder()
.addText(InetAddress.getByName(args.first()).hostAddress) .addText("域名: ${host}解析后的IP地址为: ")
.build() .addText(withContext(Dispatchers.IO) { InetAddress.getByName(host) }.hostAddress)
listener.sendGroupMessage(message.groupId, msg) .build()
message.reply(msg)
} catch (_: UnknownHostException) {
message.reply("未知的主机名: $host")
} catch (e: Exception) {
message.reply("未知错误: ${e.message}")
}
} }
} }
@@ -7,17 +7,21 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.pixiv.Ranking import cn.rtast.fancybot.entity.pixiv.Ranking
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.net.URI import java.net.URI
@CommandDescription("获取Pixiv上的图片")
class PixivCommand : BaseCommand() { class PixivCommand : BaseCommand() {
override val commandNames = listOf("/pixiv", "/p") override val commandNames = listOf("/p")
private val pixivRankingURL = "https://proxy.rtast.cn/https/www.pixiv.net/ranking.php?format=json&mode=daily&p=1" private val pixivRankingURL = "https://proxy.rtast.cn/https/www.pixiv.net/ranking.php?format=json&mode=daily&p=1"
private val imageProxyURL = "https://pixiv.re" private val imageProxyURL = "https://pixiv.re"
@@ -25,30 +29,37 @@ class PixivCommand : BaseCommand() {
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addText("发送`/pixiv <id> | rank` 来进行操作哦~")
.addText("发送/pixiv <id> | rank 来进行操作哦~")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
return return
} }
when (val keyword = args.first()) { when (val keyword = args.first()) {
"rank", "排名", "r" -> { "rank", "排名", "r" -> {
val msg = MessageChain.Builder() val node = NodeMessageChain.Builder()
.addAt(message.sender.userId) .addMessageChain(
.addText("今日Pixiv Ranking~") MessageChain.Builder().addText("今日Pixiv Ranking~").build(),
.addNewLine() message.sender.userId
)
val result = Http.get<Ranking>(pixivRankingURL) val result = Http.get<Ranking>(pixivRankingURL)
result.contents.asSequence().take(5).forEach { result.contents.asSequence().take(5).forEach {
try { try {
val msg = MessageChain.Builder()
val imageBase64 = URI(it.getOriginUrl()).toURL().readBytes().encodeToBase64() val imageBase64 = URI(it.getOriginUrl()).toURL().readBytes().encodeToBase64()
msg.addText(it.title) msg.addImage(imageBase64, true)
.addImage(imageBase64, true) .addText("标题: ${it.title}")
.addNewLine() .addNewLine()
.addText("用户: ${it.userName}(${it.userId}) | 作品ID: ${it.illustId}")
.addNewLine()
.addText("日期: ${it.date}")
node.addMessageChain(msg.build(), configManager.selfId)
} catch (_: Exception) { } catch (_: Exception) {
} }
} }
listener.sendGroupMessage(message.groupId, msg.build()) node.addMessageChain(MessageChain.Builder()
.addText("图片来源: Pixiv")
.build(), configManager.selfId)
message.reply(node.build())
return return
} }
@@ -56,19 +67,14 @@ class PixivCommand : BaseCommand() {
try { try {
val id = keyword.toLong() val id = keyword.toLong()
val imageBase64 = URI("$imageProxyURL/$id.png").toURL().readBytes().encodeToBase64() val imageBase64 = URI("$imageProxyURL/$id.png").toURL().readBytes().encodeToBase64()
println(imageBase64)
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("来咯~ 你要的图片~~~")
.addImage(imageBase64, true) .addImage(imageBase64, true)
.addText("图片来源: Pixiv")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
} catch (_: Exception) { } catch (_: Exception) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder().addText("输入错误~检查一下有没有输错吧~").build()
.addAt(message.sender.userId) message.reply(msg)
.addText("输入错误~检查一下有没有输错吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
} }
@@ -7,20 +7,21 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("生成二维码")
class QRCodeCommand : BaseCommand() { class QRCodeCommand : BaseCommand() {
override val commandNames = listOf("/qrcode", "/qr", "/二维码") override val commandNames = listOf("/qr")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val content = args.joinToString(" ") val content = args.joinToString(" ")
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addImage("https://api.rtast.cn/api/generate_qr?data=$content") .addImage("https://api.rtast.cn/api/generate_qr?data=$content")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
} }
} }
@@ -7,52 +7,45 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.segment.Node
import cn.rtast.rob.segment.PlainText
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
private fun generateNodeMessage(targetName: String, targetId: String, times: Int = 10): NodeMessageChain { private fun generateNodeMessage(targetId: String, times: Int = 10): NodeMessageChain {
val nodeMsg = NodeMessageChain.Builder() val nodeMsg = NodeMessageChain.Builder()
repeat(times) { repeat(times) {
val node = Node( val msg = MessageChain.Builder().addText("我是傻逼").build()
Node.Data( nodeMsg.addMessageChain(msg, targetId.toLong())
targetName,
targetId,
listOf(PlainText(PlainText.Data("我是傻逼")))
)
)
nodeMsg.addNode(node)
} }
return nodeMsg.build() return nodeMsg.build()
} }
@CommandDescription("骂自己(好爽)")
class ShotSelfCommand : BaseCommand() { class ShotSelfCommand : BaseCommand() {
override val commandNames = listOf("骂我") override val commandNames = listOf("骂我")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
listener.sendGroupForwardMsg( listener.sendGroupForwardMsg(message.groupId, generateNodeMessage(message.sender.userId.toString()))
message.groupId,
generateNodeMessage(message.sender.nickname, message.sender.userId.toString())
)
} }
} }
@CommandDescription("骂别人(更爽了")
class ShotOtherCommand : BaseCommand() { class ShotOtherCommand : BaseCommand() {
override val commandNames = listOf("") override val commandNames = listOf("")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
message.reply("发送`骂 @某人`可以骂他~") listener.sendGroupForwardMsg(message.groupId, generateNodeMessage(message.sender.userId.toString(), 20))
return return
} }
var times = if (args.size == 1) 10 else if (args.last() == "") 10 else args.last().toInt() var times = if (args.size == 1) 10 else if (args.last() == "") 10 else args.last().toInt()
if (times >= 200) times = 10 if (times >= 200) times = 10
val target = message.message.find { it.type == ArrayMessageType.at }?.data!! val target = message.message.find { it.type == ArrayMessageType.at }?.data!!
listener.sendGroupForwardMsg(message.groupId, generateNodeMessage(target.name!!, target.qq!!, times)) listener.sendGroupForwardMsg(message.groupId, generateNodeMessage(target.qq!!, times))
} }
} }
@@ -0,0 +1,50 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/10/1
*/
package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.stock.StockSymbolQuery
import cn.rtast.fancybot.util.Http
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
import cn.rtast.rob.util.ob.asNode
class StockDataCommand : BaseCommand() {
override val commandNames = listOf("sd", "股票")
private val apiUrl = "https://proxy.rtast.cn/https/finnhub.io"
private val apiKey = "crtmph1r01qv68qhn8n0crtmph1r01qv68qhn8ng"
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val method = args.first()
when (method) {
"q" -> {
val messages = mutableListOf<MessageChain>()
val symbol = args.joinToString(" ")
val response = Http.get<StockSymbolQuery>(
"$apiUrl/api/v1/search",
mapOf(
"q" to symbol,
"token" to apiKey,
)
)
messages.add(MessageChain.Builder().addText("共搜索到${response.count}条结果").build())
response.result.forEach {
val tempMsg = MessageChain.Builder()
.addText("股票代码: ${it.displaySymbol}(${it.symbol}, ${it.description})")
.build()
messages.add(tempMsg)
}
message.reply(messages.asNode(configManager.selfId))
}
}
}
}
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.weather.Geo import cn.rtast.fancybot.entity.weather.Geo
import cn.rtast.fancybot.entity.weather.Weather import cn.rtast.fancybot.entity.weather.Weather
@@ -25,8 +26,9 @@ import java.awt.Color
import java.awt.Font import java.awt.Font
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
@CommandDescription("查询天气")
class WeatherCommand : BaseCommand() { class WeatherCommand : BaseCommand() {
override val commandNames = listOf("/weather", "/天气", "天气") override val commandNames = listOf("天气")
private val canvasWidth = 800 private val canvasWidth = 800
private val canvasHeight = 600 private val canvasHeight = 600
@@ -7,20 +7,27 @@
package cn.rtast.fancybot.commands.lookup package cn.rtast.fancybot.commands.lookup
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.wiki.PageInfoResponse import cn.rtast.fancybot.entity.wiki.PageInfoResponse
import cn.rtast.fancybot.entity.wiki.WikipediaResponse import cn.rtast.fancybot.entity.wiki.WikipediaResponse
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.extractPlainTextFromHtml
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import org.jsoup.Jsoup
@CommandDescription("查询wiki百科")
class WikipediaCommand : BaseCommand() { class WikipediaCommand : BaseCommand() {
override val commandNames = listOf("/wiki", "/wk") override val commandNames = listOf("/wiki", "/wk")
private val wikipediaAPI = "https://proxy.rtast.cn/https/zh.wikipedia.org/w/api.php" private val wikipediaAPI = "https://proxy.rtast.cn/https/zh.wikipedia.org/w/api.php"
private fun String.extractPlainTextFromHtml(): String {
val doc = Jsoup.parse(this)
return doc.text()
}
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager import cn.rtast.fancybot.configManager
import cn.rtast.rob.entity.ArrayMessage import cn.rtast.rob.entity.ArrayMessage
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
@@ -14,8 +15,9 @@ import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("防撤回(获取消息)")
class AntiRevokeCommand : BaseCommand() { class AntiRevokeCommand : BaseCommand() {
override val commandNames = listOf("/revoke", "/rv", "/防撤回") override val commandNames = listOf("/revoke", "/rv")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (message.sender.userId !in configManager.admins) message.reply("你不许用防撤回") if (message.sender.userId !in configManager.admins) message.reply("你不许用防撤回")
@@ -0,0 +1,70 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/26
*/
package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.bullshit.BullShit
import cn.rtast.fancybot.util.Resources
import cn.rtast.fancybot.util.str.fromJson
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener
import kotlin.random.Random
class BullShitGenerateCommand : BaseCommand() {
override val commandNames = listOf("/gpbt", "狗屁不通")
private val bullShitData = String(Resources.loadFromResourcesAsBytes("misc/bull_shit.json")!!)
.fromJson<BullShit>()
private fun <T> shuffleList(list: List<T>): Iterator<T> {
val pool = mutableListOf<T>().apply { addAll(list) }.toMutableList()
repeat(1) { pool.addAll(list) }
return generateSequence {
pool.shuffle()
pool
}.flatten().iterator()
}
private fun getFamousQuote(nextQuote: Iterator<String>, beforeList: List<String>, afterList: List<String>): String {
var quote = nextQuote.next()
quote = quote.replace("a", beforeList.random())
quote = quote.replace("b", afterList.random())
return quote
}
private fun newParagraph(): String {
return ".\n\n "
}
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val topic = args.joinToString(" ")
val nextFamousQuote = shuffleList(bullShitData.famous)
val nextBosh = shuffleList(bullShitData.bosh)
val output = StringBuilder()
while (output.length < 6000) {
val branch = Random.nextInt(100)
if (branch < 5) {
output.append(newParagraph())
} else if (branch < 20) {
output.append(getFamousQuote(nextFamousQuote, bullShitData.before, bullShitData.after))
} else {
output.append(nextBosh.next())
}
}
val finalText = output.toString().replace("x", topic)
val node = NodeMessageChain.Builder()
.addMessageChain(MessageChain.Builder().addText(finalText).build(), configManager.selfId)
.build()
message.reply(node)
message.sender.groupPoke()
}
}
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.compiler.GLOTPayload import cn.rtast.fancybot.entity.compiler.GLOTPayload
import cn.rtast.fancybot.entity.compiler.GLOTResponse import cn.rtast.fancybot.entity.compiler.GLOTResponse
import cn.rtast.fancybot.entity.compiler.KCSPayload import cn.rtast.fancybot.entity.compiler.KCSPayload
@@ -18,6 +19,7 @@ import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("执行不同语言的代码片段")
class CompilerCommand : BaseCommand() { class CompilerCommand : BaseCommand() {
override val commandNames = listOf("/compiler", "/exec") override val commandNames = listOf("/compiler", "/exec")
@@ -26,11 +28,7 @@ class CompilerCommand : BaseCommand() {
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() message.reply("使用`/exec` <语言> <代码> 即可执行~")
.addAt(message.sender.userId)
.addText("使用`/exec` <语言> <代码> 即可执行~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return return
} }
val language = args.first() val language = args.first()
@@ -51,7 +49,7 @@ class CompilerCommand : BaseCommand() {
} }
} }
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addReply(message.messageId)
.addText("执行结果如下:") .addText("执行结果如下:")
.addNewLine() .addNewLine()
.addText(response.replace("<outStream>", "").replace("</outStream>", "")) .addText(response.replace("<outStream>", "").replace("</outStream>", ""))
@@ -1,28 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/8/30
*/
package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.entity.FKXQS
import cn.rtast.fancybot.util.Http
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
class FKXQSCommand : BaseCommand() {
override val commandNames = listOf("/fkxqs", "/fk", "/疯狂星期四")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val response = Http.get<FKXQS>("https://api.shadiao.pro/kfc").data.text
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText(response)
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.Hitokoto import cn.rtast.fancybot.entity.Hitokoto
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
@@ -14,8 +15,9 @@ import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("一言")
class HitokotoCommand : BaseCommand() { class HitokotoCommand : BaseCommand() {
override val commandNames = listOf("/hitokoto", "/1", "一言", "1") override val commandNames = listOf("/1")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val response = Http.get<Hitokoto>("https://v1.hitokoto.cn/?c=b") val response = Http.get<Hitokoto>("https://v1.hitokoto.cn/?c=b")
@@ -5,14 +5,16 @@
*/ */
package cn.rtast.fancybot.commands.record package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.util.file.JrrpManager import cn.rtast.fancybot.util.file.JrrpManager
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("今日人品~")
class JrrpCommand : BaseCommand() { class JrrpCommand : BaseCommand() {
override val commandNames = listOf("/jrrp", "/今日人品") override val commandNames = listOf("/jrrp", "/今日人品")
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.util.Resources import cn.rtast.fancybot.util.Resources
import cn.rtast.fancybot.util.drawCircularImage import cn.rtast.fancybot.util.drawCircularImage
import cn.rtast.fancybot.util.makeGif import cn.rtast.fancybot.util.makeGif
@@ -21,6 +22,7 @@ import com.madgag.gif.fmsware.GifDecoder
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.net.URI import java.net.URI
@CommandDescription("撅撅你")
class JueCommand : BaseCommand() { class JueCommand : BaseCommand() {
override val commandNames = listOf("") override val commandNames = listOf("")
@@ -0,0 +1,41 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/8/30
*/
package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.KFC
import cn.rtast.fancybot.util.Http
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.OneBotListener
import java.time.DayOfWeek
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
@CommandDescription("今天是疯狂星期四!")
class KFCCommand : BaseCommand() {
override val commandNames = listOf("/fkxqs", "/kfc")
private fun isThursday(): Boolean {
val dateTime = LocalDateTime.ofInstant(
Instant.now(),
ZoneId.of("Asia/Shanghai")
)
return dateTime.dayOfWeek == DayOfWeek.THURSDAY
}
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (!isThursday()) {
message.reply("很可惜今天并不是星期四~")
return
}
message.reply(Http.get<KFC>("https://api.shadiao.pro/kfc").data.text)
}
}
@@ -7,11 +7,13 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("资料卡点赞")
class LikeMeCommand : BaseCommand() { class LikeMeCommand : BaseCommand() {
override val commandNames = listOf("赞我") override val commandNames = listOf("赞我")
@@ -7,12 +7,14 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("RUA!")
class RUACommand : BaseCommand() { class RUACommand : BaseCommand() {
override val commandNames = listOf("/rua", "rua") override val commandNames = listOf("/rua", "rua")
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.enums.CountryList import cn.rtast.fancybot.entity.enums.CountryList
import cn.rtast.fancybot.util.randomBooleanWithProbability import cn.rtast.fancybot.util.randomBooleanWithProbability
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
@@ -14,8 +15,9 @@ import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("人生重开模拟器")
class RemakeCommand : BaseCommand() { class RemakeCommand : BaseCommand() {
override val commandNames = listOf("/remake", "/重开", "remake", "重开") override val commandNames = listOf("remake")
private val locations = listOf( private val locations = listOf(
"厕所", "首都", "农村", "市区", "厕所", "首都", "农村", "市区",
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.configManager import cn.rtast.fancybot.configManager
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
@@ -16,6 +17,7 @@ import org.simplejavamail.api.mailer.config.TransportStrategy
import org.simplejavamail.email.EmailBuilder import org.simplejavamail.email.EmailBuilder
import org.simplejavamail.mailer.MailerBuilder import org.simplejavamail.mailer.MailerBuilder
@CommandDescription("发送邮件!")
class SendMailCommand : BaseCommand() { class SendMailCommand : BaseCommand() {
override val commandNames = listOf("/mail") override val commandNames = listOf("/mail")
@@ -42,11 +44,7 @@ class SendMailCommand : BaseCommand() {
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() message.reply("发送`/mail <收件人地址>`即可发送测试邮件~")
.addAt(message.sender.userId)
.addText("发送`/mail <收件人地址>`即可发送测试邮件~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return return
} }
if (message.sender.userId !in configManager.admins) { if (message.sender.userId !in configManager.admins) {
@@ -59,10 +57,6 @@ class SendMailCommand : BaseCommand() {
} }
val target = args.first() val target = args.first()
this.sendMail(target) this.sendMail(target)
val msg = MessageChain.Builder() message.reply("正在发送邮件, 请查收~(可能会出现在垃圾桶中~)")
.addAt(message.sender.userId)
.addText("正在发送邮件, 请查收~(可能会出现在垃圾桶中~)")
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
@@ -5,8 +5,9 @@
*/ */
package cn.rtast.fancybot.commands.record package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.entity.ShortLink import cn.rtast.fancybot.entity.ShortLink
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
@@ -14,8 +15,9 @@ import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("生成短链接")
class ShortLinkCommand : BaseCommand() { class ShortLinkCommand : BaseCommand() {
override val commandNames = listOf("/s", "/sl", "/shortlink", "/short") override val commandNames = listOf("/s")
private val shortLinkApi = "https://api.rtast.cn" private val shortLinkApi = "https://api.rtast.cn"
@@ -1,48 +1,30 @@
/* /*
* Copyright © 2024 RTAkland * Copyright © 2024 RTAkland
* Author: RTAkland * Author: RTAkland
* Date: 2024/9/23 * Date: 2024/9/29
*/ */
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.entity.Setu
import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.str.fromArrayJson
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.segment.Node
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.net.URI
class TenSetuCommand : BaseCommand() { class TenSetuCommand : BaseCommand() {
override val commandNames = listOf("十张色图") override val commandNames = listOf("十张色图")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val nodeMsg = NodeMessageChain.Builder() val msg = MessageChain.Builder()
val response = Http.get("https://api.rtast.cn/api/setu?size=10").fromArrayJson<List<Setu>>() .addText("指令已经迁移到兑换列表中")
response.forEach {
if (it.r18) {
try {
val imageBase64 = URI(it.urls.large).toURL().readBytes().encodeToBase64()
val tempMsg = MessageChain.Builder().addImage(imageBase64, true).build()
val tempNode = Node(Node.Data("", message.userId.toString(), tempMsg.finalArrayMsgList))
nodeMsg.addNode(tempNode)
} catch (_: Exception) {
}
}
}
val footerMsg = MessageChain.Builder()
.addText("图片数量可能不足10张~")
.addNewLine() .addNewLine()
.addText("因为过滤了R18的图片~") .addText("使用`/rdm 十张色图`来兑换吧~")
.addNewLine()
.addText("(需要20cm的牛子长度来兑换)")
.addNewLine()
.addText("此指令已废弃")
.build() .build()
val footerNode = Node(Node.Data("", message.userId.toString(), footerMsg.finalArrayMsgList)) message.reply(msg)
nodeMsg.addNode(footerNode)
listener.sendGroupForwardMsg(message.groupId, nodeMsg.build())
} }
} }
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.misc package cn.rtast.fancybot.commands.misc
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.entity.PrivateMessage import cn.rtast.rob.entity.PrivateMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
@@ -15,6 +16,7 @@ import cn.rtast.rob.util.ob.OneBotListener
val users = mutableMapOf<Long, Long>() val users = mutableMapOf<Long, Long>()
@CommandDescription("自闭去吧你")
class ZiBiCommand : BaseCommand() { class ZiBiCommand : BaseCommand() {
override val commandNames = listOf("/自闭", "自闭") override val commandNames = listOf("/自闭", "自闭")
@@ -29,17 +31,19 @@ class ZiBiCommand : BaseCommand() {
.addText("私聊发送`我想开了`即可取消禁言~") .addText("私聊发送`我想开了`即可取消禁言~")
.build() .build()
message.reply(msg) message.reply(msg)
users[message.sender.userId] = message.groupId
} catch (_: Exception) { } catch (_: Exception) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addText("你输入有误所以我决定让你自闭1天~") .addText("你输入有误所以我决定让你自闭1天~")
.build() .build()
message.reply(msg) message.reply(msg)
message.sender.ban(86400) message.sender.ban(86400)
} finally {
users[message.sender.userId] = message.groupId
} }
} }
} }
@CommandDescription("我好像突然想开了")
class UnsetZiBiCommand : BaseCommand() { class UnsetZiBiCommand : BaseCommand() {
override val commandNames = listOf("我想开了") override val commandNames = listOf("我想开了")
@@ -0,0 +1,42 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("查询自己牛子的长度")
class MyNiuziCommand : BaseCommand() {
override val commandNames = listOf("我的牛子", "mp")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val niuzi = niuziManager.getUser(message.sender.userId)
if (niuzi == null) {
message.reply("你还没有牛子呢, 发送`牛子签到`来领取一根专属于你的牛子吧~")
return
}
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你的牛子长度为: ${niuzi.length}cm")
val niuziString = when (niuzi.length) {
in -999.0..0.0 -> "你的牛子已经凹进去了!!!!"
in 0.1..6.0 -> "小小的也很可爱呢~"
in 6.1..15.0 -> "好长的牛子!"
in 15.1..30.0 -> "你的牛子已经快突破天际了!!!"
else -> "牛子也太长啦把天捅穿啦!!!!!!"
}
msg.addText(niuziString)
listener.sendGroupMessage(message.groupId, msg.build())
}
}
@@ -0,0 +1,163 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.commands
import cn.rtast.fancybot.niuziBankManager
import cn.rtast.fancybot.niuziManager
import cn.rtast.fancybot.util.getUserName
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
private suspend fun noAccount(message: GroupMessage) {
message.reply("你还没有银行账户呢, 发送`创建账户`来创建一个账户吧~")
}
private const val INTEREST_RATE = 0.0054
@CommandDescription("牛子银行根命令")
class NiuziBankCommand : BaseCommand() {
override val commandNames = listOf("牛子银行")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val niuziCommands = commands.filter {
it::class.simpleName?.startsWith("Niuzi")!! && !it::class.simpleName?.lowercase()?.contains("redeem")!!
}.joinToString("\n") { it.commandNames.joinToString(",") { join -> "`$join`" } }
val msg = MessageChain.Builder()
.addText("发送")
.addNewLine()
.addText(niuziCommands)
.addNewLine()
.addText("即可做出对应的操作")
.addNewLine()
.addText("银行利率是0.54%")
.build()
message.reply(msg)
}
}
@CommandDescription("查询牛子银行的余额")
class BankBalanceCommand : BaseCommand() {
override val commandNames = listOf("余额查询")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val balanceData = niuziBankManager.getUser(message.sender.userId)
if (balanceData == null) {
noAccount(message)
return
}
message.reply("你的账户余额还有: ${balanceData.balance}cm")
}
}
@CommandDescription("创建一个空的牛子银行账户")
class CreateBankAccountCommand : BaseCommand() {
override val commandNames = listOf("创建账户")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (niuziBankManager.getUser(message.sender.userId) != null) {
message.reply("你已经有账户了!")
return
}
val userInfo = listener.getGroupMemberInfo(message.groupId, message.sender.userId)
niuziBankManager.createBlankAccount(message.sender.userId, userInfo.card ?: userInfo.nickname)
message.reply("成功创建了一个账户!")
}
}
@CommandDescription("用于牛子银行之间转账")
class BankTransferCommand : BaseCommand() {
override val commandNames = listOf("银行转账")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val currentUserBalance = niuziBankManager.getUser(message.sender.userId)
if (currentUserBalance == null) {
noAccount(message)
return
}
val target = message.message.find { it.type == ArrayMessageType.at }?.data?.qq!!.toLong()
if (niuziBankManager.getUser(target) == null) {
message.reply("他还没有银行账户呢, 提醒他创建一个账户吧~(发送`创建账户`)")
return
}
val amount = args.last().toDouble()
if (amount > currentUserBalance.balance) {
message.reply("你的牛子长度不够转账!")
return
}
val username = listener.getUserName(message.groupId, message.sender.userId)
val result = niuziBankManager.transfer(message.sender.userId, target, amount, username)
message.reply("转账成功! 你在银行内剩余的牛子长度为: ${result?.balance}")
}
}
@CommandDescription("牛子银行提现")
class WithdrawCommand : BaseCommand() {
override val commandNames = listOf("取牛子")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val amount = args.last().toDouble()
val currentBalance = niuziBankManager.getUser(message.sender.userId)
val niuzi = niuziManager.getUser(message.sender.userId)
if (currentBalance == null) {
noAccount(message)
return
}
if (niuzi == null) {
message.reply("你还没有认领牛子呢, 发送`牛子签到`来领取一根吧")
return
}
if (amount > currentBalance.balance) {
message.reply("你的牛子长度不足无法取出 >>> $amount")
return
}
if (amount <= 0) {
message.reply("取出的长度必须大于0!")
return
}
val username = listener.getUserName(message.groupId, message.sender.userId)
val result = niuziBankManager.withdraw(message.sender.userId, amount, username)
niuziManager.updateLength(message.sender.userId, amount + amount * INTEREST_RATE)
message.reply("取牛子成功, 你现在还剩${result.balance}cm的牛子在银行内")
}
}
@CommandDescription("牛子银行存入")
class DepositCommand : BaseCommand() {
override val commandNames = listOf("存牛子")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val currentBalance = niuziBankManager.getUser(message.sender.userId)
val niuzi = niuziManager.getUser(message.sender.userId)
val amount = args.last().toDouble()
if (amount <= 0) {
message.reply("存款必须大于0!")
return
}
if (currentBalance == null) {
noAccount(message)
return
}
if (niuzi == null) {
message.reply("你还没有认领牛子呢, 发送`牛子签到`来领取一根吧")
return
}
if (amount > niuzi.length) {
message.reply("你身上的牛子不够用啦, 没办法存进银行! >>> ${niuzi.length}")
return
}
val username = listener.getUserName(message.groupId, message.sender.userId)
val self = niuziManager.updateLength(message.sender.userId, -amount)
val result = niuziBankManager.deposit(message.sender.userId, amount, username)
message.reply("存入成功你身上的牛子还有${self?.length}cm 银行账户内还有: ${result.balance}cm")
}
}
@@ -0,0 +1,75 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("来一起激情击剑吧!")
class NiuziJiJianCommand : BaseCommand() {
override val commandNames = listOf("击剑", "jj")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
message.reply("发送`击剑 @xxx`即可对某人进行击剑")
return
}
val target = message.message.find { it.type == ArrayMessageType.at }!!.data
val targetId = target.qq!!.toLong()
if (targetId == 0L) {
val msg = MessageChain.Builder()
.addReply(message.messageId)
.addText("你的只有一根牛子,他们牛子太多啦你战胜不了他们的~")
.addNewLine()
.addText("所以你不能和他们击剑~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
if (message.sender.userId == targetId) {
message.reply("你不能和自己击剑啊")
return
}
if (!niuziManager.exists(message.sender.userId)) {
message.reply("你还没有牛子呢, 发送`牛子签到`领取你的牛子吧~")
return
}
if (!niuziManager.exists(targetId)) {
message.reply("对方还没有牛子呢, 提醒他领取一根牛子吧~")
return
}
if (niuziManager.getUser(message.sender.userId)?.length!! < 0.0) {
message.reply("你的牛子已经凹进去了没办法进行击剑~发送`牛子签到`来增加你的牛子长度吧~")
return
}
if (niuziManager.getUser(targetId)?.length!! < 0.0) {
message.reply("他已经没有牛子啦!(他的牛子已经凹进去了!!)你不能和他击剑")
return
}
val result = niuziManager.jijian(message.sender.userId, targetId)
if (result.first) {
message.reply("你以已绝对的长度在这场击剑中获胜了~, 你的牛子增加了${result.second}cm")
} else {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("很不幸你的牛子没能战胜${target.name}, 你的牛子缩短了${result.second}cm")
.addNewLine()
.addText("对方的牛子增加了${result.second}cm~")
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
}
@@ -0,0 +1,34 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("查询别人的牛子长度")
class NiuziQueryCommand : BaseCommand() {
override val commandNames = listOf("牛子查询")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
message.reply("输入`牛子查询 @某人`即可查询他的牛子长度")
return
}
val target = message.message.find { it.type == ArrayMessageType.at }?.data?.qq!!.toLong()
val targetNiuzi = niuziManager.getUser(target)
if (targetNiuzi == null) {
message.reply("他还没有牛子")
return
}
message.reply("他的牛子长度为: ${targetNiuzi.length}cm")
}
}
@@ -0,0 +1,45 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/26
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.niuziBankManager
import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("查询所有人的牛子的排行榜")
class NiuziRankCommand : BaseCommand() {
override val commandNames = listOf("牛子排行榜", "牛子排行")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val allNiuzi = niuziManager.getAllNiuzi().sortedBy { it.length }.reversed()
val msg = MessageChain.Builder().addText("牛子长度排行榜如下").addNewLine()
allNiuzi.forEach {
msg.addText("[${it.nickname}] | ${it.length}cm").addNewLine()
}
message.reply(msg.build())
}
}
@CommandDescription("查询所有人的银行账户余额排行榜")
class NiuziBankRankCommand : BaseCommand() {
override val commandNames = listOf("牛子富豪榜", "富豪榜")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val allNiuziBankAccounts = niuziBankManager.getAllAccount()
.sortedBy { it.balance }.reversed()
val msg = MessageChain.Builder().addText("牛子银行富豪榜排行如下").addNewLine()
allNiuziBankAccounts.forEach {
msg.addText("[${it.nickname}] | ${it.balance}cm").addNewLine()
}
message.reply(msg.build())
}
}
@@ -5,56 +5,49 @@
*/ */
package cn.rtast.fancybot.commands.record package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.itemManager import cn.rtast.fancybot.itemManager
import cn.rtast.fancybot.signManager import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
class RedeemCommand : BaseCommand() { @CommandDescription("使用牛子长度兑换物品")
override val commandNames = listOf("/redeem", "/兑换", "/rdm") class NiuziRedeemCommand : BaseCommand() {
override val commandNames = listOf("/rdm")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) { if (args.isEmpty()) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addReply(message.messageId)
.addText("发送 /rdm <物品名称> 即可兑换哦!") .addText("发送 /rdm <物品名称> 即可兑换哦!")
.addNewLine() .addNewLine()
.addText("发送 /rdm list 即可查看所有可兑换的物品~") .addText("发送 /rdm list 即可查看所有可兑换的物品~")
.addNewLine() .addNewLine()
.addText("发送 /mp 可以查看自己拥有的点数~") .addText("发送 `我的牛子` 可以查看自己的牛子长度~")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) listener.sendGroupMessage(message.groupId, msg)
return return
} }
val status = signManager.getStatus(message.sender.userId) val status = niuziManager.getUser(message.sender.userId)
if (status == null) { if (status == null) {
val msg = MessageChain.Builder() message.reply("你还没有签到过呢要签到一次才能兑换哦~")
.addAt(message.sender.userId)
.addText("你还没有签到过呢要签到一次才能兑换哦~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return return
} }
val item = args.first() val item = args.first()
if (item == "list" || item == "列表") { if (item == "list" || item == "列表") {
val priceTable = val priceTable = itemManager.items.joinToString("\n")
itemManager.items.joinToString("\n") { "[${it.itemNames.joinToString("|")}]:${it.itemPrice}积分" } { "[${it.itemNames.joinToString("|")}]:${it.itemPrice}cm" }
val msg = MessageChain.Builder() message.reply(priceTable)
.addAt(message.sender.userId)
.addNewLine()
.addText(priceTable)
.build()
listener.sendGroupMessage(message.groupId, msg)
return return
} }
val selectedItem = itemManager.items.find { it.itemNames.any { any -> any == item } } val selectedItem = itemManager.items.find { it.itemNames.any { any -> any == item } }
if (selectedItem == null) { if (selectedItem == null) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addReply(message.messageId)
.addText("没有找到你想兑换的东西呢") .addText("没有找到你想兑换的东西呢")
.addNewLine() .addNewLine()
.addText("你可以发送 /rdm list来查看所有可兑换的物品") .addText("你可以发送 /rdm list来查看所有可兑换的物品")
@@ -63,24 +56,26 @@ class RedeemCommand : BaseCommand() {
return return
} }
val selectedItemPrice = selectedItem.itemPrice val selectedItemPrice = selectedItem.itemPrice
if (selectedItemPrice > status.points) { if (selectedItemPrice > status.length) {
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addReply(message.messageId)
.addText("你的积分不够兑换这个物品呢~") .addText("你的牛子长度不够兑换这个物品呢~")
.addNewLine() .addNewLine()
.addText("你有: ${status.points}个积分, 兑换需要: $selectedItemPrice 个积分~\"") .addText("你有: ${status.length}cm, 兑换需要: $selectedItemPrice cm~\"")
.build() .build()
listener.sendGroupMessage(message.groupId, msg) listener.sendGroupMessage(message.groupId, msg)
return return
} }
val afterStatus = signManager.redeemItem(message.sender.userId, selectedItemPrice)?.points!! val afterStatus = niuziManager.redeemItem(message.sender.userId, selectedItemPrice)?.length!!
val action = selectedItem.redeemInGroup(listener, message, afterStatus)
val msg = MessageChain.Builder() val msg = MessageChain.Builder()
.addAt(message.sender.userId) .addReply(message.messageId)
.addText("兑换成功正在发送奖品中~") .addText("兑换成功! 你花费了${selectedItemPrice}cm来兑换奖品, 还剩${afterStatus}cm")
.addNewLine() .addNewLine()
.addText("你花费了 $selectedItemPrice 点积分来兑换奖品, 还剩 $afterStatus 点积分") .addText("-------------------")
.addNewLine()
.addMessageChain(action)
.build() .build()
listener.sendGroupMessage(message.groupId, msg) message.reply(msg)
selectedItem.redeemGroup(listener, message, afterStatus)
} }
} }
@@ -0,0 +1,37 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.niuziManager
import cn.rtast.fancybot.util.getUserName
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("牛子签到~")
class NiuziSignCommand : BaseCommand() {
override val commandNames = listOf("牛子签到", "签到")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (niuziManager.isSigned(message.sender.userId)) {
message.reply("你今天已经对你的牛子使用了签到啦,明天再来吧~")
return
}
val username = listener.getUserName(message.groupId, message.sender.userId)
val afterStatus = niuziManager.sign(message.sender.userId, username)
val msg = MessageChain.Builder()
.addReply(message.messageId)
.addText("签到成功~")
.addNewLine()
.addText("你的牛子增加了${afterStatus.first}cm~ 总长度为: ${afterStatus.second?.length}")
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
@@ -0,0 +1,51 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.commands.niuzi
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.OneBotListener
@CommandDescription("将自己的牛子长度转账给别人")
class NiuziTransferCommand : BaseCommand() {
override val commandNames = listOf("牛子转账", "zz")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
message.reply("发送`牛子转账 @某人 <长度>` 即可把自己的牛子长度转账给TA")
return
}
val target = message.message.find { it.type == ArrayMessageType.at }!!.data.qq!!.toLong()
val targetNiuzi = niuziManager.getUser(target)
if (targetNiuzi == null) niuziManager.createBlankUser(target)
val transferLength = args.last().toDouble()
val currentNiuzi = niuziManager.getUser(message.sender.userId)
if (currentNiuzi == null) {
message.reply("你没有牛子没办法转账")
return
}
if (currentNiuzi.length <= 0.0) {
message.reply("你已经没有牛子可以转账了")
return
}
if (currentNiuzi.length < transferLength) {
message.reply("你的牛子长度不够转账这么多 >>>${transferLength}cm")
return
}
if (transferLength <= 0) {
message.reply("长度必须大于0!")
return
}
niuziManager.updateLength(message.sender.userId, -transferLength)
niuziManager.updateLength(target, transferLength)
message.reply("转账成功, 你的长度减少了: ${transferLength}cm, 对方的长度增加了 ${transferLength}cm")
}
}
@@ -7,6 +7,8 @@
package cn.rtast.fancybot.commands.parse package cn.rtast.fancybot.commands.parse
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.util.makeGif
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.toByteArray import cn.rtast.fancybot.util.toByteArray
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
@@ -14,6 +16,9 @@ import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import com.madgag.gif.fmsware.GifDecoder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.awt.Color import java.awt.Color
import java.awt.Font import java.awt.Font
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
@@ -21,6 +26,7 @@ import java.net.URI
import javax.imageio.ImageIO import javax.imageio.ImageIO
import kotlin.math.roundToInt import kotlin.math.roundToInt
@CommandDescription("将图片转换成ASCII字符画!")
class AsciiArtCommand : BaseCommand() { class AsciiArtCommand : BaseCommand() {
override val commandNames = listOf("/ascii", "/asc") override val commandNames = listOf("/ascii", "/asc")
@@ -63,7 +69,7 @@ class AsciiArtCommand : BaseCommand() {
} }
private fun String.saveAsciiArtToImage(width: Int, height: Int): String { private fun String.saveAsciiArtToImage(width: Int, height: Int): BufferedImage {
val imgWidth = width * FONT_SIZE / 2 val imgWidth = width * FONT_SIZE / 2
val imgHeight = height * FONT_SIZE / 2 val imgHeight = height * FONT_SIZE / 2
val img = BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB) val img = BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB)
@@ -77,22 +83,44 @@ class AsciiArtCommand : BaseCommand() {
g2d.drawString(line, 0, (index + 1) * FONT_SIZE) g2d.drawString(line, 0, (index + 1) * FONT_SIZE)
} }
g2d.dispose() g2d.dispose()
return img.toByteArray().encodeToBase64() return img
} }
suspend fun callback(message: GroupMessage) { suspend fun callback(message: GroupMessage) {
if (message.sender.userId in waitingList) { if (message.sender.userId !in waitingList) return
if (message.message.any { it.type == ArrayMessageType.image }) { waitingList.removeIf { it == message.sender.userId }
val url = message.message.find { it.type == ArrayMessageType.image }!!.data.file!! if (message.message.any { it.type == ArrayMessageType.image }
val bufferedImage = ImageIO.read(URI(url).toURL()) || message.message.any { it.type == ArrayMessageType.mface }) {
val imageBase64 = val url = if (message.message.any { it.type == ArrayMessageType.image })
bufferedImage.convertToAscii().saveAsciiArtToImage(bufferedImage.width, bufferedImage.height) message.message.find { it.type == ArrayMessageType.image }!!.data.file!!
val msg = MessageChain.Builder().addImage(imageBase64, true).build() else message.message.find { it.type == ArrayMessageType.mface }!!.data.url!!
message.reply(msg) val gifStream = withContext(Dispatchers.IO) { URI(url).toURL().openStream() }
} else { val decoder = GifDecoder()
message.reply("回复错误已取消本次操作") try {
decoder.read(gifStream)
if (decoder.frameCount == 0) {
val bufferedImage = withContext(Dispatchers.IO) { ImageIO.read(URI(url).toURL()) }
val imageBase64 = bufferedImage.convertToAscii()
.saveAsciiArtToImage(bufferedImage.width, bufferedImage.height)
.toByteArray().encodeToBase64()
val msg = MessageChain.Builder().addImage(imageBase64, true).build()
message.reply(msg)
} else {
println("Making gif ascii art, frames: ${decoder.frameCount}")
val frames = (0 until decoder.frameCount).map { decoder.getFrame(it) }
val asciiFrames = mutableListOf<BufferedImage>()
val width = frames.first().width
val height = frames.first().height
frames.forEach { asciiFrames.add(it.convertToAscii().saveAsciiArtToImage(width, height)) }
val gifBytes = decoder.makeGif(asciiFrames)
val gifBase64 = gifBytes.encodeToBase64()
message.reply(MessageChain.Builder().addImage(gifBase64, true).build())
}
} catch (_: Exception) {
message.reply("处理GIF失败")
} }
waitingList.removeIf { it == message.sender.userId } } else {
message.reply("回复错误已取消本次操作")
} }
} }
} }
@@ -7,18 +7,17 @@
package cn.rtast.fancybot.commands.parse package cn.rtast.fancybot.commands.parse
import cn.rtast.fancybot.entity.bili.ShortUrl import cn.rtast.fancybot.entity.bili.*
import cn.rtast.fancybot.entity.bili.UserStat
import cn.rtast.fancybot.entity.bili.VideoStat
import cn.rtast.fancybot.entity.bili.ViewCount
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.Resources import cn.rtast.fancybot.util.Resources
import cn.rtast.fancybot.util.drawCustomImage import cn.rtast.fancybot.util.drawCustomImage
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.str.formatNumber import cn.rtast.fancybot.util.str.formatNumber
import cn.rtast.fancybot.util.str.setTruncat import cn.rtast.fancybot.util.str.fromJson
import cn.rtast.fancybot.util.str.setTruncate
import cn.rtast.fancybot.util.toByteArray import cn.rtast.fancybot.util.toByteArray
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@@ -115,7 +114,7 @@ object BVParseCommand {
g2d.drawString(reply, 300, 290) g2d.drawString(reply, 300, 290)
g2d.drawString(share, 300, 200) g2d.drawString(share, 300, 200)
// draw video title // draw video title
val truncatedText = setTruncat(title, g2d) val truncatedText = setTruncate(title, g2d)
g2d.font = titleFont g2d.font = titleFont
g2d.drawString(truncatedText, 20, 70) g2d.drawString(truncatedText, 20, 70)
// draw author name // draw author name
@@ -150,7 +149,29 @@ object BVParseCommand {
} }
} }
suspend fun parse(listener: OneBotListener, bvid: String, message: GroupMessage) { suspend fun parse(listener: OneBotListener, message: GroupMessage) {
// parse bilibili video with a link, bvid or b23.tv link
val bvid = if (message.rawMessage.startsWith("BV")) {
message.rawMessage
} else if (message.rawMessage.split(" ").last().startsWith("https://b23.tv/")) {
val shortUrl = message.rawMessage.split(" ").last()
BVParseCommand.getShortUrlBVID(shortUrl)
} else if (message.message.find { it.type == ArrayMessageType.json } != null) {
val card = message.message.find { it.type == ArrayMessageType.json }!!
.data.data!!.toString().fromJson<CardShare>()
val shortUrl = if (card.meta.detail == null) {
if (!card.meta.news?.tag!!.contains("哔哩哔哩")) return
card.meta.news.jumpUrl
} else {
if (!card.meta.detail.title.contains("哔哩哔哩")) return
card.meta.detail.qqDocUrl
}
BVParseCommand.getShortUrlBVID(shortUrl)
} else {
message.rawMessage.split("?").first()
.split("/")
.last { it.isNotEmpty() && it.isNotBlank() }
}
val videoInfo = this.getVideoStat(bvid) val videoInfo = this.getVideoStat(bvid)
val viewCount = this.getViewCount(bvid, videoInfo.data.cid) val viewCount = this.getViewCount(bvid, videoInfo.data.cid)
val shortUrl = this.generateShortUrl(bvid, videoInfo.data.aid) val shortUrl = this.generateShortUrl(bvid, videoInfo.data.aid)
@@ -15,7 +15,7 @@ import cn.rtast.fancybot.util.drawCustomImage
import cn.rtast.fancybot.util.drawString import cn.rtast.fancybot.util.drawString
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.str.formatNumberEnglish import cn.rtast.fancybot.util.str.formatNumberEnglish
import cn.rtast.fancybot.util.str.setTruncat import cn.rtast.fancybot.util.str.setTruncate
import cn.rtast.fancybot.util.toByteArray import cn.rtast.fancybot.util.toByteArray
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
@@ -100,11 +100,11 @@ object GitHubParseCommand {
if (repoStat.fork) { if (repoStat.fork) {
g2d.font = forkParentFont g2d.font = forkParentFont
val parentName = repoStat.parent?.fullName!! val parentName = repoStat.parent?.fullName!!
val truncatedParentFullName = setTruncat("复刻自 $parentName", g2d, 1000) val truncatedParentFullName = setTruncate("复刻自 $parentName", g2d, 1000)
g2d.drawString(truncatedParentFullName, 80, 335) g2d.drawString(truncatedParentFullName, 80, 335)
} }
g2d.font = titleCustomFont g2d.font = titleCustomFont
val truncatedFullNameText = setTruncat(repoStat.fullName, g2d, 1000) val truncatedFullNameText = setTruncate(repoStat.fullName, g2d, 1000)
g2d.drawString(truncatedFullNameText, 80, 280) g2d.drawString(truncatedFullNameText, 80, 280)
g2d.font = descriptionCustomFont g2d.font = descriptionCustomFont
g2d.drawString(repoStat.description ?: "暂无描述~", 80, 400, 800) g2d.drawString(repoStat.description ?: "暂无描述~", 80, 400, 800)
@@ -7,6 +7,7 @@
package cn.rtast.fancybot.commands.parse package cn.rtast.fancybot.commands.parse
import cn.rtast.fancybot.annotations.CommandDescription
import cn.rtast.fancybot.util.makeGif import cn.rtast.fancybot.util.makeGif
import cn.rtast.fancybot.util.str.encodeToBase64 import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
@@ -17,6 +18,7 @@ import cn.rtast.rob.util.ob.OneBotListener
import com.madgag.gif.fmsware.GifDecoder import com.madgag.gif.fmsware.GifDecoder
import java.net.URI import java.net.URI
@CommandDescription("倒放GIF")
class ReverseGIFCommand : BaseCommand() { class ReverseGIFCommand : BaseCommand() {
override val commandNames = listOf("倒放") override val commandNames = listOf("倒放")
@@ -34,6 +36,7 @@ class ReverseGIFCommand : BaseCommand() {
suspend fun callback(message: GroupMessage) { suspend fun callback(message: GroupMessage) {
if (message.sender.userId !in waitingList) return if (message.sender.userId !in waitingList) return
waitingList.removeIf { it == message.sender.userId }
val gifUrl = if (message.message.find { it.type == ArrayMessageType.mface } == null) { val gifUrl = if (message.message.find { it.type == ArrayMessageType.mface } == null) {
message.message.find { it.type == ArrayMessageType.image }!!.data.file!! message.message.find { it.type == ArrayMessageType.image }!!.data.file!!
} else { } else {
@@ -42,14 +45,13 @@ class ReverseGIFCommand : BaseCommand() {
val base64String = this.reverseGif(gifUrl) val base64String = this.reverseGif(gifUrl)
val msg = MessageChain.Builder().addImage(base64String, true).build() val msg = MessageChain.Builder().addImage(base64String, true).build()
message.reply(msg) message.reply(msg)
waitingList.removeIf { it == message.sender.userId }
} }
} }
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) { override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (message.sender.userId !in waitingList) { if (message.sender.userId !in waitingList) {
waitingList.add(message.sender.userId)
message.reply("发送一张动图来继续操作") message.reply("发送一张动图来继续操作")
waitingList.add(message.sender.userId)
} else { } else {
message.reply("发送错误本次操作已取消") message.reply("发送错误本次操作已取消")
waitingList.removeIf { it == message.sender.userId } waitingList.removeIf { it == message.sender.userId }
@@ -1,53 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/4
*/
package cn.rtast.fancybot.commands.record
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.signManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.UserRole
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
class MyPointCommand : BaseCommand() {
override val commandNames = listOf("/我的点数", "/mp")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
// query target's point
if (args.isNotEmpty() && (message.sender.role == UserRole.admin || message.sender.userId in configManager.admins)) {
val targetId = args.first().toLong()
val targetData = signManager.getStatus(targetId)
val msg = MessageChain.Builder().addAt(message.sender.userId)
if (targetData == null) {
msg.addText("用户不存在, 需要先签到一次才能查询点数呢~")
} else {
msg.addText("用户: ${targetData.id} 的点数有: ${targetData.points}")
}
listener.sendGroupMessage(message.groupId, msg.build())
return
}
// query self point
val status = signManager.getStatus(message.sender.userId)
if (status == null) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你还没有签到过呢! 先发送‘/签到’再来查询吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
} else {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你当前的点数为: ${status.points}")
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
}
@@ -1,153 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/8
*/
package cn.rtast.fancybot.commands.record
import cn.rtast.fancybot.niuziManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.enums.ArrayMessageType
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
class NiuziSignCommand : BaseCommand() {
override val commandNames = listOf("牛子签到")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (niuziManager.isSigned(message.sender.userId)) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你今天已经对你的牛子使用了签到啦,明天再来吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
val afterStatus = niuziManager.sign(message.sender.userId)
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("签到成功~")
.addNewLine()
.addText("你的牛子增加了${afterStatus.first}cm~ 总长度为: ${afterStatus.second?.length}")
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
class JiJianCommand : BaseCommand() {
override val commandNames = listOf("击剑", "jj")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (args.isEmpty()) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("发送`击剑 @xxx`即可对某人进行击剑")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
val target = message.message.find { it.type == ArrayMessageType.at }!!.data
val targetId = target.qq!!.toLong()
if (targetId == 0L) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你的只有一根牛子,他们牛子太多啦你战胜不了他们的~")
.addNewLine()
.addText("所以你不能和他们击剑~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
if (message.sender.userId == targetId) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你不能和自己击剑啊")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
if (!niuziManager.exists(message.sender.userId)) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你还没有牛子呢, 发送`牛子签到`领取你的牛子吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
if (!niuziManager.exists(targetId)) {
val msg = MessageChain.Builder()
.addAt(targetId)
.addText("对方还没有牛子呢, 提醒他领取一根牛子吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
if (niuziManager.getUser(message.sender.userId)?.length!! < 0.0) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你的牛子已经凹进去了没办法进行击剑~发送`牛子签到来增加你的牛子长度吧~`")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
if (niuziManager.getUser(targetId)?.length!! < 0.0) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("他已经没有牛子啦!(他的牛子已经凹进去了!!)你不能和他击剑")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
val result = niuziManager.jijian(message.sender.userId, targetId)
if (result.first) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你以已绝对的长度在这场击剑中获胜了~, 你的牛子增加了${result.second}cm")
.build()
listener.sendGroupMessage(message.groupId, msg)
} else {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("很不幸你的牛子没能战胜${target.name}, 你的牛子缩短了${result.second}cm")
.addNewLine()
.addText("对方的牛子增加了${result.second}cm~")
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
}
class MyNiuziCommand : BaseCommand() {
override val commandNames = listOf("我的牛子")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
val niuzi = niuziManager.getUser(message.sender.userId)
if (niuzi == null) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你还没有牛子呢, 发送`牛子签到`来领取一根专属于你的牛子吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你的牛子长度为: ${niuzi.length}cm")
val niuziString = when (niuzi.length) {
in -999.0..0.0 -> "你的牛子已经凹进去了!!!!"
in 0.1..6.0 -> "小小的也很可爱呢~"
in 6.1..15.0 -> "好长的牛子!"
in 15.1..30.0 -> "你的牛子已经快突破天际了!!!"
else -> "牛子也太长啦把天捅穿啦!!!!!!"
}
msg.addText(niuziString)
listener.sendGroupMessage(message.groupId, msg.build())
}
}
@@ -1,38 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/8/30
*/
package cn.rtast.fancybot.commands.record
import cn.rtast.fancybot.signManager
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.BaseCommand
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
class SignCommand : BaseCommand() {
override val commandNames = listOf("/签到", "/sign")
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
if (signManager.isSigned(message.sender.userId)) {
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你今天已经签到过啦, 明天再来吧~")
.build()
listener.sendGroupMessage(message.groupId, msg)
return
}
val randomPoint = signManager.sign(message.sender.userId)
val msg = MessageChain.Builder()
.addAt(message.sender.userId)
.addText("你获得了 $randomPoint 点分数!")
.addNewLine()
.addText("发送‘/我的点数’ 或者 ‘/mp’ 即可查看当前的点数")
.build()
listener.sendGroupMessage(message.groupId, msg)
}
}
@@ -22,11 +22,17 @@ data class Config(
val imageType: ImageType, val imageType: ImageType,
val openAIAPIHost: String, val openAIAPIHost: String,
val openAIAPIKey: String, val openAIAPIKey: String,
val openAIModel: String,
val smtpHost: String, val smtpHost: String,
val smtpPort: Int, val smtpPort: Int,
val smtpUser: String, val smtpUser: String,
val smtpPassword: String, val smtpPassword: String,
val smtpFromAddress: String, val smtpFromAddress: String,
val admins: List<Long>, val admins: List<Long>,
val enableAntiRevoke: Boolean val enableAntiRevoke: Boolean,
val llamaUrl: String,
val llamaModel: String,
val qqMusicApiUrl: String,
val startUpNoticeUser: Long,
val selfId: Long
) )
@@ -7,7 +7,7 @@
package cn.rtast.fancybot.entity package cn.rtast.fancybot.entity
data class FKXQS( data class KFC(
val data: Data, val data: Data,
) { ) {
data class Data( data class Data(
@@ -1,24 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/3
*/
package cn.rtast.fancybot.entity
data class MCPing(
val version: Version,
val players: Players,
val favicon: String?
) {
data class Version(
val protocol: Int,
val name: String,
)
data class Players(
val online: Int,
val max: Int,
)
}
@@ -0,0 +1,26 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.entity.bgm
import com.google.gson.annotations.SerializedName
data class BGMSearch(
val list: List<Result>
) {
data class Result(
val url: String,
val images: Images,
val name: String,
@SerializedName("name_cn")
val nameCN: String,
)
data class Images(
val large: String
)
}
@@ -1,47 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.entity.bili
import com.google.gson.annotations.SerializedName
data class Search(
val data: Data
) {
data class Data(
val result: List<Result>
)
data class Result(
@SerializedName("result_type")
val resultType: String,
val data: List<EPData>
)
data class EPData(
val url: String,
val desc: String,
val title: String,
@SerializedName("org_title")
val orgTitle: String,
val cover: String,
@SerializedName("pubtime")
val pubTime: Long,
@SerializedName("media_score")
val mediaScore: MediaScore,
@SerializedName("index_show")
val indexShow: String,
val areas: String,
val styles: String,
)
data class MediaScore(
val score: Float,
@SerializedName("user_count")
val userCount: Int,
)
}
@@ -0,0 +1,8 @@
package cn.rtast.fancybot.entity.bullshit
data class BullShit(
val after: List<String>,
val before: List<String>,
val bosh: List<String>,
val famous: List<String>
)
@@ -0,0 +1,28 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.entity.db
import org.jetbrains.exposed.sql.Table
object NiuziBankTable : Table("niuzi_bank") {
val id = long("id").autoIncrement()
val userId = long("userId").uniqueIndex()
val timestamp = long("timestamp")
val balance = double("balance")
val interestRate = double("interest_rate")
val nickname = varchar("nickname", 255)
override val primaryKey = PrimaryKey(id)
}
data class NiuziBankAccount(
val userId: Long,
val balance: Double,
val interestRate: Double,
val timestamp: Long,
val nickname: String
)
@@ -9,16 +9,18 @@ package cn.rtast.fancybot.entity.db
import org.jetbrains.exposed.sql.Table import org.jetbrains.exposed.sql.Table
object NiuziTable : Table("niuzu") { object NiuziTable : Table("niuzi") {
val length = double("length") val length = double("length")
val id = long("id").autoIncrement() val id = long("id").autoIncrement()
val userId = long("userId").uniqueIndex() val userId = long("userId").uniqueIndex()
val timestamp = long("timestamp") val timestamp = long("timestamp")
val nickname = varchar("nickname", 255)
override val primaryKey = PrimaryKey(id) override val primaryKey = PrimaryKey(id)
} }
data class Niuzi( data class Niuzi(
val userId: Long, val userId: Long,
val length: Double, val length: Double,
val timestamp: Long val timestamp: Long,
val nickname: String,
) )
@@ -1,19 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/8/30
*/
package cn.rtast.fancybot.entity.db
import org.jetbrains.exposed.sql.Table
object SignTable : Table("sign") {
val id = integer("id").autoIncrement()
val userId = long("userId").uniqueIndex()
val timestamp = long("timestamp")
val point = long("point")
override val primaryKey = PrimaryKey(id)
}
@@ -11,7 +11,8 @@ import cn.rtast.fancybot.entity.enums.GPTUserRole
data class ChatCompletionsPayload( data class ChatCompletionsPayload(
val model: String, val model: String,
val messages: List<Message> val messages: List<Message>,
val stream: Boolean = false
) { ) {
data class Message( data class Message(
val content: String, val content: String,
@@ -0,0 +1,16 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.entity.gpt
data class LlamaResponse(
val message: Message
) {
data class Message(
val content: String,
)
}
@@ -0,0 +1,31 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/25
*/
package cn.rtast.fancybot.entity.music.qq
import com.google.gson.annotations.SerializedName
data class QQMSearch(
val response: Response,
) {
data class Response(
val data: Data
)
data class Data(
val song: Songs
)
data class Songs(
val list: List<Song>
)
data class Song(
@SerializedName("songid")
val songId: Long,
)
}
@@ -7,16 +7,25 @@
package cn.rtast.fancybot.entity.pixiv package cn.rtast.fancybot.entity.pixiv
import com.google.gson.annotations.SerializedName
data class Ranking( data class Ranking(
val contents: List<Content> val contents: List<Content>
) { ) {
data class Content( data class Content(
val title: String, val title: String,
val tags: List<String>, val tags: List<String>,
val url: String val url: String,
@SerializedName("user_name")
val userName: String,
@SerializedName("user_id")
val userId: Long,
@SerializedName("illust_id")
val illustId: Long,
val date: String,
) { ) {
fun getOriginUrl(): String { fun getOriginUrl(): String {
return url.replace("https://i.pximg.net", "https://proxy.rtast.cn/https/pixiv.microyu.workers.dev") return url.replace("https://i.pximg.net", "https://i.pixiv.re")
.replace("/c/240x480/img-master/", "/img-original/") .replace("/c/240x480/img-master/", "/img-original/")
.replace("_master1200", "") .replace("_master1200", "")
} }
@@ -5,11 +5,15 @@
*/ */
package cn.rtast.fancybot.entity package cn.rtast.fancybot.entity.setu
import com.google.gson.annotations.SerializedName
data class Setu( data class Setu(
val urls: URLS, val urls: URLS,
val r18: Boolean val r18: Boolean,
@SerializedName("author_id")
val authorId: Long,
) { ) {
data class URLS( data class URLS(
val large: String val large: String
@@ -0,0 +1,22 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/29
*/
package cn.rtast.fancybot.entity.setu
data class SetuV2(
val pid: Long,
val uid: Long,
val title: String,
val author: String,
val urls: URLS,
val r18: Boolean,
val tags: List<String>
) {
data class URLS(
val regular: String,
)
}
@@ -0,0 +1,19 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/10/1
*/
package cn.rtast.fancybot.entity.stock
data class StockSymbolQuery(
val count: Int,
val result: List<Result>
) {
data class Result(
val description: String,
val displaySymbol: String,
val symbol: String,
)
}
@@ -16,14 +16,15 @@ import cn.rtast.rob.util.ob.OneBotListener
class BaisiItem : Item() { class BaisiItem : Item() {
override val itemNames = listOf("baisi", "白丝", "bs") override val itemNames = listOf("baisi", "白丝", "bs")
override val itemPrice = 70 override val itemPrice = 3.0
override suspend fun redeemInGroup(listener: OneBotListener, message: GroupMessage, after: Long) { override suspend fun redeemInGroup(
listener: OneBotListener,
message: GroupMessage,
after: Double
): MessageChain.Builder {
val url = Http.get<Baisi>("https://v2.api-m.com/api/baisi").data val url = Http.get<Baisi>("https://v2.api-m.com/api/baisi").data
val msg = MessageChain.Builder() val msg = MessageChain.Builder().addImage(url)
.addAt(message.sender.userId) return msg
.addImage(url)
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
@@ -16,14 +16,15 @@ import cn.rtast.rob.util.ob.OneBotListener
class HeisiItem : Item() { class HeisiItem : Item() {
override val itemNames = listOf("heisi", "黑丝", "hs") override val itemNames = listOf("heisi", "黑丝", "hs")
override val itemPrice = 70 override val itemPrice = 3.0
override suspend fun redeemInGroup(listener: OneBotListener, message: GroupMessage, after: Long) { override suspend fun redeemInGroup(
listener: OneBotListener,
message: GroupMessage,
after: Double
): MessageChain.Builder {
val url = Http.get<Baisi>("https://v2.api-m.com/api/heisi").data val url = Http.get<Baisi>("https://v2.api-m.com/api/heisi").data
val msg = MessageChain.Builder() val msg = MessageChain.Builder().addImage(url)
.addAt(message.sender.userId) return msg
.addImage(url)
.build()
listener.sendGroupMessage(message.groupId, msg)
} }
} }
@@ -0,0 +1,33 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/27
*/
package cn.rtast.fancybot.items
import cn.rtast.fancybot.niuziManager
import cn.rtast.fancybot.util.item.Item
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener
class NiuziItem : Item() {
override val itemNames = listOf("牛子", "nz", "niuzi")
override val itemPrice = 10.0
override suspend fun redeemInGroup(
listener: OneBotListener,
message: GroupMessage,
after: Double
): MessageChain.Builder {
val before = niuziManager.getUser(message.sender.userId)!!
val afterNiuzi = niuziManager.updateLength(message.sender.userId, -2.0)!!
val msg = MessageChain.Builder()
.addText("你的牛子到账啦, 你的牛子现在有${afterNiuzi.length}cm长呢!")
.addNewLine()
.addText("(之前的长度是${before.length}cm!)")
return msg
}
}
@@ -7,25 +7,34 @@
package cn.rtast.fancybot.items package cn.rtast.fancybot.items
import cn.rtast.fancybot.entity.Setu import cn.rtast.fancybot.entity.setu.Setu
import cn.rtast.fancybot.niuziManager
import cn.rtast.fancybot.util.Http import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.item.Item import cn.rtast.fancybot.util.item.Item
import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.str.fromArrayJson import cn.rtast.fancybot.util.str.fromArrayJson
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
import java.net.URI
class SetuItem : Item() { class SetuItem : Item() {
override val itemNames = listOf("setu", "色图", "st") override val itemNames = listOf("setu", "色图", "st")
override val itemPrice = 80 override val itemPrice = 4.0
override suspend fun redeemInGroup(listener: OneBotListener, message: GroupMessage, after: Long) { override suspend fun redeemInGroup(
val url = Http.get("https://api.rtast.cn/api/setu") listener: OneBotListener,
.fromArrayJson<List<Setu>>().first().urls.large message: GroupMessage,
val msg = MessageChain.Builder() after: Double
.addAt(message.sender.userId) ): MessageChain.Builder {
.addImage(url) val response = Http.get("https://api.rtast.cn/api/setu")
.build() .fromArrayJson<List<Setu>>().first()
listener.sendGroupMessage(message.groupId, msg) if (response.r18) {
niuziManager.updateLength(message.sender.userId, itemPrice)
return MessageChain.Builder().addText("不好意思这张图片是R18所以不能发~, 牛子长度已经退还~")
}
val imageBase64 = URI(response.urls.large).toURL().readBytes().encodeToBase64()
val msg = MessageChain.Builder().addImage(imageBase64, true)
return msg
} }
} }
@@ -0,0 +1,89 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/28
*/
package cn.rtast.fancybot.items
import cn.rtast.fancybot.configManager
import cn.rtast.fancybot.entity.setu.Setu
import cn.rtast.fancybot.entity.setu.SetuV2
import cn.rtast.fancybot.util.Http
import cn.rtast.fancybot.util.item.Item
import cn.rtast.fancybot.util.str.encodeToBase64
import cn.rtast.fancybot.util.str.fromArrayJson
import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.NodeMessageChain
import cn.rtast.rob.util.ob.OneBotListener
import cn.rtast.rob.util.ob.asNode
import java.net.URI
private fun getImages(r18: Boolean): NodeMessageChain {
val msg = mutableListOf<MessageChain>()
if (r18) {
val response = Http.get("https://api.rtast.cn/api/setu/v2?size=10")
.fromArrayJson<List<SetuV2>>()
msg.add(MessageChain.Builder().addText("因为是R18所以你需要自行访问链接来查看图片~").build())
response.forEach {
try {
val tempMsg = MessageChain.Builder()
.addText(it.urls.regular)
.addNewLine()
.addText("标题: ${it.title}")
.addNewLine()
.addText("作品ID: ${it.pid}")
.addNewLine()
.addText("作者: ${it.author}(${it.uid})")
.addNewLine()
.addText("标签: ${it.tags.joinToString(" | ")}")
.build()
msg.add(tempMsg)
} catch (_: Exception) {
}
}
} else {
val response = Http.get("https://api.rtast.cn/api/setu?size=10").fromArrayJson<List<Setu>>()
response.filter { !it.r18 }.map { it.urls.large }.forEach {
try {
val imageBase64 = URI(it).toURL().readBytes().encodeToBase64()
val tempMsg = MessageChain.Builder().addImage(imageBase64, true).build()
msg.add(tempMsg)
} catch (_: Exception) {
}
}
}
return msg.asNode(configManager.selfId)
}
class TenSetuItem : Item() {
override val itemNames = listOf("十张色图")
override val itemPrice = 20.0
override suspend fun redeemInGroup(
listener: OneBotListener,
message: GroupMessage,
after: Double
): MessageChain.Builder {
val msg = getImages(false)
message.reply(msg)
return MessageChain.Builder()
}
}
class TenSetuR18Item : Item() {
override val itemNames = listOf("十张色图r")
override val itemPrice = 50.0
override suspend fun redeemInGroup(
listener: OneBotListener,
message: GroupMessage,
after: Double
): MessageChain.Builder {
message.reply(getImages(true))
return MessageChain.Builder()
}
}
@@ -9,8 +9,8 @@ package cn.rtast.fancybot.util
import cn.rtast.fancybot.ROOT_PATH import cn.rtast.fancybot.ROOT_PATH
import cn.rtast.fancybot.entity.db.JrrpTable import cn.rtast.fancybot.entity.db.JrrpTable
import cn.rtast.fancybot.entity.db.NiuziBankTable
import cn.rtast.fancybot.entity.db.NiuziTable import cn.rtast.fancybot.entity.db.NiuziTable
import cn.rtast.fancybot.entity.db.SignTable
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SchemaUtils
@@ -20,7 +20,7 @@ suspend fun initDatabase() {
Database.connect("jdbc:sqlite:file:$ROOT_PATH/data.sqlite", "org.sqlite.JDBC") Database.connect("jdbc:sqlite:file:$ROOT_PATH/data.sqlite", "org.sqlite.JDBC")
suspendedTransaction { suspendedTransaction {
SchemaUtils.createMissingTablesAndColumns(JrrpTable) SchemaUtils.createMissingTablesAndColumns(JrrpTable)
SchemaUtils.createMissingTablesAndColumns(SignTable) SchemaUtils.createMissingTablesAndColumns(NiuziBankTable)
SchemaUtils.createMissingTablesAndColumns(NiuziTable) SchemaUtils.createMissingTablesAndColumns(NiuziTable)
} }
} }
@@ -1,17 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.util
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
fun Long.parseTimeStamp(): LocalDateTime {
val instant = Instant.ofEpochMilli(this)
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault())
}
@@ -13,12 +13,14 @@ import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
fun GifDecoder.makeGif(frames: List<BufferedImage>): ByteArray { fun GifDecoder.makeGif(frames: List<BufferedImage>): ByteArray {
val byteArrayOutputStream = ByteArrayOutputStream() val estimatedSize = frames.size * 50 * 1024
val byteArrayOutputStream = ByteArrayOutputStream(estimatedSize)
val encoder = AnimatedGifEncoder() val encoder = AnimatedGifEncoder()
encoder.start(byteArrayOutputStream) encoder.start(byteArrayOutputStream)
encoder.setRepeat(0) encoder.setRepeat(0)
for (i in frames.indices) { val delays = frames.indices.map { this.getDelay(this.frameCount - it - 1) }
encoder.setDelay(this.getDelay(this.frameCount - i - 1)) frames.indices.forEach { i ->
encoder.setDelay(delays[i])
encoder.addFrame(frames[i]) encoder.addFrame(frames[i])
} }
encoder.finish() encoder.finish()
@@ -16,8 +16,8 @@ import okhttp3.RequestBody.Companion.toRequestBody
object Http { object Http {
val jsonMediaType = "application/json; charset=utf-8".toMediaType() private val jsonMediaType = "application/json; charset=utf-8".toMediaType()
val jsonHeader = mapOf( private val jsonHeader = mapOf(
"Content-Type" to "application/json; charset=utf-8", "Content-Type" to "application/json; charset=utf-8",
"Accept" to "application/json" "Accept" to "application/json"
) )
@@ -7,9 +7,15 @@
package cn.rtast.fancybot.util package cn.rtast.fancybot.util
import cn.rtast.rob.util.ob.OneBotListener
import kotlin.random.Random import kotlin.random.Random
fun randomBooleanWithProbability(probability: Double): Boolean { fun randomBooleanWithProbability(probability: Double): Boolean {
val randomValue = Random.nextInt(100) val randomValue = Random.nextInt(100)
return randomValue <= (probability * 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
}
@@ -10,7 +10,7 @@ package cn.rtast.fancybot.util
import java.io.InputStream import java.io.InputStream
object Resources { object Resources {
fun loadFromResources(filename: String): InputStream { fun loadFromResources(filename: String): InputStream? {
return this::class.java.classLoader.getResourceAsStream(filename) return this::class.java.classLoader.getResourceAsStream(filename)
} }
@@ -11,22 +11,29 @@ import cn.rtast.fancybot.entity.Config
import cn.rtast.fancybot.util.JsonFileHandler import cn.rtast.fancybot.util.JsonFileHandler
class ConfigManager : JsonFileHandler<Config>("config.json") { class ConfigManager : JsonFileHandler<Config>("config.json") {
val ncmAPI get() = this.read<Config>().ncmAPI private val config = this.read<Config>()
val wsAddress get() = this.read<Config>().wsAddress val ncmAPI = config.ncmAPI
val wsPort get() = this.read<Config>().port val wsAddress = config.wsAddress
val accessToken get() = this.read<Config>().accessToken val wsPort = config.port
val wsType get() = this.read<Config>().wsType val accessToken = config.accessToken
val listeningGroups get() = this.read<Config>().listeningGroups val wsType = config.wsType
val qweatherKey get() = this.read<Config>().qweatherKey val listeningGroups = config.listeningGroups
val githubKey get() = this.read<Config>().githubKey val qweatherKey = config.qweatherKey
val imageType get() = this.read<Config>().imageType val githubKey = config.githubKey
val openAIAPIHost get() = this.read<Config>().openAIAPIHost val imageType = config.imageType
val openAIAPIKey get() = this.read<Config>().openAIAPIKey val openAIAPIHost = config.openAIAPIHost
val smtpHost get() = this.read<Config>().smtpHost val openAIAPIKey = config.openAIAPIKey
val smtpPort get() = this.read<Config>().smtpPort val openAIModel = config.openAIModel
val smtpUser get() = this.read<Config>().smtpUser val smtpHost = config.smtpHost
val smtpPassword get() = this.read<Config>().smtpPassword val smtpPort = config.smtpPort
val smtpFromAddress get() = this.read<Config>().smtpFromAddress val smtpUser = config.smtpUser
val admins get() = this.read<Config>().admins val smtpPassword = config.smtpPassword
val enableAntiRevoke get() = this.read<Config>().enableAntiRevoke val smtpFromAddress = config.smtpFromAddress
val admins = config.admins
val enableAntiRevoke = config.enableAntiRevoke
val llamaUrl = config.llamaUrl
val llamaModel = config.llamaModel
val qqMusicApiUrl = config.qqMusicApiUrl
val startUpNoticeUser = config.startUpNoticeUser
val selfId = config.selfId
} }
@@ -0,0 +1,94 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/9/24
*/
package cn.rtast.fancybot.util.file
import cn.rtast.fancybot.entity.db.NiuziBankAccount
import cn.rtast.fancybot.entity.db.NiuziBankTable
import cn.rtast.fancybot.entity.db.NiuziBankTable.balance
import cn.rtast.fancybot.entity.db.NiuziBankTable.interestRate
import cn.rtast.fancybot.entity.db.NiuziBankTable.nickname
import cn.rtast.fancybot.entity.db.NiuziBankTable.timestamp
import cn.rtast.fancybot.entity.db.NiuziBankTable.userId
import cn.rtast.fancybot.entity.db.NiuziTable
import cn.rtast.fancybot.util.suspendedTransaction
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.update
import java.time.Instant
class NiuziBankManager {
suspend fun getUser(id: Long): NiuziBankAccount? {
return suspendedTransaction {
NiuziBankTable.selectAll().where { userId eq id }.map {
NiuziBankAccount(
it[userId],
it[balance],
it[interestRate],
it[timestamp],
it[nickname]
)
}.singleOrNull()
}
}
private suspend fun increaseBalance(id: Long, amount: Double, username: String) {
val current = this.getUser(id)
suspendedTransaction {
NiuziBankTable.update({ userId eq id }) {
it[balance] = current?.balance!! + amount
it[NiuziTable.timestamp] = Instant.now().epochSecond
it[nickname] = username
}
}
}
private suspend fun decreaseBalance(id: Long, amount: Double, username: String) {
this.increaseBalance(id, -amount, username)
}
suspend fun createBlankAccount(id: Long, username: String) {
suspendedTransaction {
NiuziBankTable.insert {
it[userId] = id
it[balance] = 0.0
it[timestamp] = Instant.now().epochSecond
it[interestRate] = 0.54
it[nickname] = username
}
}
}
suspend fun withdraw(id: Long, amount: Double, username: String): NiuziBankAccount {
suspendedTransaction {
this.decreaseBalance(id, amount, username)
}
return this.getUser(id)!!
}
suspend fun deposit(id: Long, amount: Double, username: String): NiuziBankAccount {
suspendedTransaction {
this.increaseBalance(id, amount, username)
}
return this.getUser(id)!!
}
suspend fun transfer(from: Long, target: Long, amount: Double, username: String): NiuziBankAccount? {
suspendedTransaction {
this.decreaseBalance(from, amount, username)
this.increaseBalance(target, amount, username)
}
return this.getUser(from)
}
suspend fun getAllAccount(): List<NiuziBankAccount> =
suspendedTransaction {
NiuziBankTable.selectAll()
.map { NiuziBankAccount(it[userId], it[balance], it[interestRate], it[timestamp], it[nickname]) }
}
}
@@ -10,6 +10,7 @@ package cn.rtast.fancybot.util.file
import cn.rtast.fancybot.entity.db.Niuzi import cn.rtast.fancybot.entity.db.Niuzi
import cn.rtast.fancybot.entity.db.NiuziTable import cn.rtast.fancybot.entity.db.NiuziTable
import cn.rtast.fancybot.entity.db.NiuziTable.length import cn.rtast.fancybot.entity.db.NiuziTable.length
import cn.rtast.fancybot.entity.db.NiuziTable.nickname
import cn.rtast.fancybot.entity.db.NiuziTable.timestamp import cn.rtast.fancybot.entity.db.NiuziTable.timestamp
import cn.rtast.fancybot.entity.db.NiuziTable.userId import cn.rtast.fancybot.entity.db.NiuziTable.userId
import cn.rtast.fancybot.util.isSameDay import cn.rtast.fancybot.util.isSameDay
@@ -22,40 +23,47 @@ import kotlin.random.Random
class NiuziManager { class NiuziManager {
private suspend fun updateLength(id: Long, newLength: Double) { suspend fun updateLength(id: Long, newLength: Double): Niuzi? {
val current = getUser(id) val current = getUser(id)
suspendedTransaction { suspendedTransaction {
NiuziTable.update({ userId eq id }) { NiuziTable.update({ userId eq id }) {
it[length] = current?.length!! + newLength it[length] = current?.length!! + newLength
} }
} }
return getUser(id)
} }
suspend fun getUser(id: Long): Niuzi? { suspend fun createBlankUser(id: Long) {
return suspendedTransaction { suspendedTransaction {
NiuziTable.selectAll().where { userId eq id }.map { NiuziTable.insert {
Niuzi( it[timestamp] = Instant.now().epochSecond
it[userId], it[length] = 0.0
it[length], it[userId] = id
it[timestamp] }
)
}.singleOrNull()
} }
} }
suspend fun getUser(id: Long): Niuzi? =
suspendedTransaction {
NiuziTable.selectAll().where { userId eq id }.map {
Niuzi(it[userId], it[length], it[timestamp], it[nickname])
}.singleOrNull()
}
suspend fun isSigned(id: Long): Boolean { suspend fun isSigned(id: Long): Boolean {
val record = getUser(id) val record = getUser(id)
return record?.timestamp?.isSameDay(Instant.now().epochSecond) ?: false return record?.timestamp?.isSameDay(Instant.now().epochSecond) ?: false
} }
suspend fun sign(id: Long): Pair<Double, Niuzi?> { suspend fun sign(id: Long, username: String): Pair<Double, Niuzi?> {
val randomLength = Random.nextDouble(-5.0, 10.0) val randomLength = Random.nextDouble(1.0, 10.0)
if (getUser(id) == null) { if (getUser(id) == null) {
suspendedTransaction { suspendedTransaction {
NiuziTable.insert { NiuziTable.insert {
it[userId] = id it[userId] = id
it[timestamp] = Instant.now().epochSecond it[timestamp] = Instant.now().epochSecond
it[length] = 0.0 it[length] = 0.0
it[nickname] = username
} }
} }
} }
@@ -85,4 +93,19 @@ class NiuziManager {
} }
return success to randomLength return success to randomLength
} }
suspend fun redeemItem(id: Long, itemPrice: Double): Niuzi? {
val current = getUser(id)
suspendedTransaction {
NiuziTable.update({ userId eq id }) {
it[length] = current?.length!! - itemPrice
}
}
return getUser(id)
}
suspend fun getAllNiuzi(): List<Niuzi> =
suspendedTransaction {
NiuziTable.selectAll().map { Niuzi(it[userId], it[length], it[timestamp], it[nickname]) }
}
} }
@@ -1,76 +0,0 @@
/*
* Copyright © 2024 RTAkland
* Author: RTAkland
* Date: 2024/8/30
*/
package cn.rtast.fancybot.util.file
import cn.rtast.fancybot.entity.db.JrrpRecord
import cn.rtast.fancybot.entity.db.SignTable
import cn.rtast.fancybot.entity.db.SignTable.point
import cn.rtast.fancybot.entity.db.SignTable.timestamp
import cn.rtast.fancybot.entity.db.SignTable.userId
import cn.rtast.fancybot.util.isSameDay
import cn.rtast.fancybot.util.suspendedTransaction
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.update
import java.time.Instant
import kotlin.random.Random
class SignManager {
private suspend fun getRecord(id: Long): JrrpRecord? {
return suspendedTransaction {
SignTable.selectAll().where { userId eq id }.map {
JrrpRecord(
it[userId],
it[timestamp],
it[point],
)
}.singleOrNull()
}
}
suspend fun isSigned(id: Long): Boolean {
val record = getRecord(id)
return record?.timestamp?.isSameDay(Instant.now().epochSecond) ?: false
}
suspend fun sign(id: Long): Long {
val randomPoint = Random.nextLong(0, 101)
if (getRecord(id) == null) {
suspendedTransaction {
SignTable.insert {
it[userId] = id
it[timestamp] = Instant.now().epochSecond
it[point] = 0
}
}
}
val record = getRecord(id)
suspendedTransaction {
SignTable.update({ userId eq id }) {
it[point] = record?.points!! + randomPoint
it[timestamp] = Instant.now().epochSecond
}
}
return randomPoint
}
suspend fun getStatus(id: Long): JrrpRecord? {
return getRecord(id)
}
suspend fun redeemItem(id: Long, itemPrice: Int): JrrpRecord? {
val current = getRecord(id)
suspendedTransaction {
SignTable.update({ userId eq id }) {
it[point] = current?.points!! - itemPrice
}
}
return getRecord(id)
}
}
@@ -8,22 +8,16 @@
package cn.rtast.fancybot.util.item package cn.rtast.fancybot.util.item
import cn.rtast.rob.entity.GroupMessage import cn.rtast.rob.entity.GroupMessage
import cn.rtast.rob.entity.PrivateMessage import cn.rtast.rob.util.ob.MessageChain
import cn.rtast.rob.util.ob.OneBotListener import cn.rtast.rob.util.ob.OneBotListener
abstract class Item { abstract class Item {
abstract val itemNames: List<String> abstract val itemNames: List<String>
abstract val itemPrice: Int abstract val itemPrice: Double
protected open suspend fun redeemInGroup(listener: OneBotListener, message: GroupMessage, after: Long) {} abstract suspend fun redeemInGroup(
listener: OneBotListener,
protected open suspend fun redeemInPrivate(listener: OneBotListener, message: PrivateMessage, after: Long) {} message: GroupMessage,
after: Double
suspend fun redeemGroup(listener: OneBotListener, message: GroupMessage, after: Long) { ): MessageChain.Builder
this.redeemInGroup(listener, message, after)
}
suspend fun redeemPrivate(listener: OneBotListener, message: PrivateMessage, after: Long) {
this.redeemInPrivate(listener, message, after)
}
} }
@@ -7,10 +7,9 @@
package cn.rtast.fancybot.util.str package cn.rtast.fancybot.util.str
import org.jsoup.Jsoup
import java.awt.Graphics2D import java.awt.Graphics2D
fun setTruncat(origin: String, g2d: Graphics2D, maxWidth: Int = 500): String { fun setTruncate(origin: String, g2d: Graphics2D, maxWidth: Int = 500): String {
val fontMetrics = g2d.fontMetrics val fontMetrics = g2d.fontMetrics
val textWidth = fontMetrics.stringWidth(origin) val textWidth = fontMetrics.stringWidth(origin)
return if (textWidth > maxWidth) { return if (textWidth > maxWidth) {
@@ -42,7 +41,8 @@ fun Int.formatNumberEnglish(): String {
} }
} }
fun String.extractPlainTextFromHtml(): String { fun Int.formatToMinutes(): String {
val doc = Jsoup.parse(this) val minutes = this / 60
return doc.text() val remainingSeconds = this % 60
return "$minutes:${if (remainingSeconds < 10) "0" else ""}$remainingSeconds"
} }
+7 -1
View File
@@ -13,6 +13,7 @@
"imageType": "PNG", "imageType": "PNG",
"openAIAPIHost": "https://api.moonshot.cn", "openAIAPIHost": "https://api.moonshot.cn",
"openAIAPIKey": "114514", "openAIAPIKey": "114514",
"openAIModel": "moonshot-v1-8k",
"smtpHost": "127.0.0.1", "smtpHost": "127.0.0.1",
"smtpPort": 25, "smtpPort": 25,
"smtpUser": "114514", "smtpUser": "114514",
@@ -21,5 +22,10 @@
"admins": [ "admins": [
3458671395 3458671395
], ],
"enableAntiRevoke": true "enableAntiRevoke": true,
"llamaUrl": "http://127.0.0.1",
"llamaModel": "llama3.1",
"qqMusicApiUrl": "http://127.0.0.1:3200",
"startUpNoticeUser": 114514,
"selfId": 114514
} }
+166
View File
@@ -0,0 +1,166 @@
{
"famous": [
"爱迪生a,天才是百分之一的勤奋加百分之九十九的汗水。b",
"查尔斯·史a,一个人几乎可以在任何他怀有无限热忱的事情上成功。b",
"培根说过,深窥自己的心,而后发觉一切的奇迹在你自己。b",
"歌德曾经a,流水在碰到底处时才会释放活力。b",
"莎士比亚a,那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。b",
"戴尔·卡耐基a,多数人都拥有自己不了解的能力和机会,都有可能做到未曾梦想的事情。b",
"白哲特a,坚强的信念能赢得强者的心,并使他们变得更坚强。b",
"伏尔泰a, 不经巨大的困难,不会有伟大的事业。b",
"富勒曾经a, 苦难磨炼一些人,也毁灭另一些人。b",
"文森特·皮尔a, 改变你的想法,你就改变了自己的世界。b",
"拿破仑·希尔a, 不要等待,时机永远不会恰到好处。b",
"塞涅卡a, 生命如同寓言,其价值不在与长短,而在与内容。b",
"奥普拉·温弗瑞a, 你相信什么,你就成为什么样的人。b",
"吕凯特a, 生命不可能有两次,但许多人连一次也不善于度过。b",
"莎士比亚a, 人的一生是短的,但如果卑劣地过这一生,就太长了。b",
"笛卡儿a, 我的努力求学没有得到别的好处,只不过是愈来愈发觉自己的无知。b",
"左拉a, 生活的道路一旦选定,就要勇敢地走到底,决不回头。b",
"米歇潘a, 生命是一条艰险的峡谷,只有勇敢的人才能通过。b",
"吉姆·罗恩a, 要么你主宰生活,要么你被生活主宰。b",
"日本谚语a, 不幸可能成为通向幸福的桥梁。b",
"海贝尔a, 人生就是学校。在那里,与其说好的教师是幸福,不如说好的教师是不幸。b",
"杰纳勒尔·乔治·S·巴顿a, 接受挑战,就可以享受胜利的喜悦。b",
"德谟克利特a, 节制使快乐增加并使享受加强。b",
"裴斯泰洛齐a, 今天应做的事没有做,明天再早也是耽误了。b",
"歌德a, 决定一个人的一生,以及整个命运的,只是一瞬之间。b",
"卡耐基a, 一个不注意小事情的人,永远不会成就大事业。b",
"卢梭a, 浪费时间是一桩大罪过。b",
"康德a, 既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。b",
"克劳斯·莫瑟爵士a, 教育需要花费钱,而无知也是一样。b",
"伏尔泰a, 坚持意志伟大的事业需要始终不渝的精神。b",
"亚伯拉罕·林肯a, 你活了多少岁不算什么,重要的是你是如何度过这些岁月的。b",
"韩非a, 内外相应,言行相称。b",
"富兰克林a, 你热爱生命吗?那么别浪费时间,因为时间是组成生命的材料。b",
"马尔顿a, 坚强的信心,能使平凡的人做出惊人的事业。b",
"笛卡儿a, 读一切好书,就是和许多高尚的人谈话。b",
"塞涅卡a, 真正的人生,只有在经过艰难卓绝的斗争之后才能实现。b",
"易卜生a, 伟大的事业,需要决心,能力,组织和责任感。b",
"歌德a, 没有人事先了解自己到底有多大的力量,直到他试过以后才知道。b",
"达尔文a, 敢于浪费哪怕一个钟头时间的人,说明他还不懂得珍惜生命的全部价值。b",
"佚名a, 感激每一个新的挑战,因为它会锻造你的意志和品格。b",
"奥斯特洛夫斯基a, 共同的事业,共同的斗争,可以使人们产生忍受一切的力量。 b",
"苏轼a, 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。b",
"王阳明a, 故立志者,为学之心也;为学者,立志之事也。b",
"歌德a, 读一本好书,就如同和一个高尚的人在交谈。b",
"乌申斯基a, 学习是劳动,是充满思想的劳动。b",
"别林斯基a, 好的书籍是最贵重的珍宝。b",
"富兰克林a, 读书是易事,思索是难事,但两者缺一,便全无用处。b",
"鲁巴金a, 读书是在别人思想的帮助下,建立起自己的思想。b",
"培根a, 合理安排时间,就等于节约时间。b",
"屠格涅夫a, 你想成为幸福的人吗?但愿你首先学会吃得起苦。b",
"莎士比亚a, 抛弃时间的人,时间也抛弃他。b",
"叔本华a, 普通人只想到如何度过时间,有才能的人设法利用时间。b",
"博a, 一次失败,只是证明我们成功的决心还够坚强。 维b",
"拉罗什夫科a, 取得成就时坚持不懈,要比遭到失败时顽强不屈更重要。b",
"莎士比亚a, 人的一生是短的,但如果卑劣地过这一生,就太长了。b",
"俾斯麦a, 失败是坚忍的最后考验。b",
"池田大作a, 不要回避苦恼和困难,挺起身来向它挑战,进而克服它。b",
"莎士比亚a, 那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。b",
"希腊a, 最困难的事情就是认识自己。b",
"黑塞a, 有勇气承担命运这才是英雄好汉。b",
"非洲a, 最灵繁的人也看不见自己的背脊。b",
"培根a, 阅读使人充实,会谈使人敏捷,写作使人精确。b",
"斯宾诺莎a, 最大的骄傲于最大的自卑都表示心灵的最软弱无力。b",
"西班牙a, 自知之明是最难得的知识。b",
"塞内加a, 勇气通往天堂,怯懦通往地狱。b",
"赫尔普斯a, 有时候读书是一种巧妙地避开思考的方法。b",
"笛卡儿a, 阅读一切好书如同和过去最杰出的人谈话。b",
"邓拓a, 越是没有本领的就越加自命不凡。b",
"爱尔兰a, 越是无能的人,越喜欢挑剔别人的错儿。b",
"老子a, 知人者智,自知者明。胜人者有力,自胜者强。b",
"歌德a, 意志坚强的人能把世界放在手中像泥块一样任意揉捏。b",
"迈克尔·F·斯特利a, 最具挑战性的挑战莫过于提升自我。b",
"爱迪生a, 失败也是我需要的,它和成功对我一样有价值。b",
"罗素·贝克a, 一个人即使已登上顶峰,也仍要自强不息。b",
"马云a, 最大的挑战和突破在于用人,而用人最大的突破在于信任人。b",
"雷锋a, 自己活着,就是为了使别人过得更美好。b",
"布尔沃a, 要掌握书,莫被书掌握;要为生而读,莫为读而生。b",
"培根a, 要知道对好事的称颂过于夸大,也会招来人们的反感轻蔑和嫉妒。b",
"莫扎特a, 谁和我一样用功,谁就会和我一样成功。b",
"马克思a, 一切节省,归根到底都归结为时间的节省。b",
"莎士比亚a, 意志命运往往背道而驰,决心到最后会全部推倒。b",
"卡莱尔a, 过去一切时代的精华尽在书中。b",
"培根a, 深窥自己的心,而后发觉一切的奇迹在你自己。b",
"罗曼·罗兰a, 只有把抱怨环境的心情,化为上进的力量,才是成功的保证。b",
"孔子a, 知之者不如好之者,好之者不如乐之者。b",
"达·芬奇a, 大胆和坚定的决心能够抵得上武器的精良。b",
"叔本华a, 意志是一个强壮的盲人,倚靠在明眼的跛子肩上。b",
"黑格尔a, 只有永远躺在泥坑里的人,才不会再掉进坑里。b",
"普列姆昌德a, 希望的灯一旦熄灭,生活刹那间变成了一片黑暗。b",
"维龙a, 要成功不需要什么特别的才能,只要把你能做的小事做得好就行了。b",
"郭沫若a, 形成天才的决定因素应该是勤奋。b",
"洛克a, 学到很多东西的诀窍,就是一下子不要学很多。b",
"西班牙a, 自己的鞋子,自己知道紧在哪里。b",
"拉罗什福科a, 我们唯一不会改正的缺点是软弱。b",
"亚伯拉罕·林肯a, 我这个人走得很慢,但是我从不后退。b",
"美华纳a, 勿问成功的秘诀为何,且尽全力做你应该做的事吧。b",
"俾斯麦a, 对于不屈不挠的人来说,没有失败这回事。b",
"阿卜·日·法拉兹a, 学问是异常珍贵的东西,从任何源泉吸收都不可耻。b",
"白哲特a, 坚强的信念能赢得强者的心,并使他们变得更坚强。 b",
"查尔斯·史考伯a, 一个人几乎可以在任何他怀有无限热忱的事情上成功。 b",
"贝多芬a, 卓越的人一大优点是:在不利与艰难的遭遇里百折不饶。b",
"莎士比亚a, 本来无望的事,大胆尝试,往往能成功。b",
"卡耐基a, 我们若已接受最坏的,就再没有什么损失。b",
"德国a, 只有在人群中间,才能认识自己。b",
"史美尔斯a, 书籍把我们引入最美好的社会,使我们认识各个时代的伟大智者。b",
"冯学峰a, 当一个人用工作去迎接光明,光明很快就会来照耀着他。b",
"吉格·金克拉a, 如果你能做梦,你就能实现它。b"
],
"bosh": [
"现在, 解决x的问题, 是非常非常重要的. 所以, ",
"我们不得不面对一个非常尴尬的事实, 那就是, ",
"x的发生, 到底需要如何做到, 不x的发生, 又会如何产生. ",
"而这些并不是完全重要, 更加重要的问题是, ",
"x, 到底应该如何实现. ",
"带着这些问题, 我们来审视一下x. ",
"所谓x, 关键是x需要如何写. ",
"我们一般认为, 抓住了问题的关键, 其他一切则会迎刃而解.",
"问题的关键究竟为何? ",
"x因何而发生?",
"每个人都不得不面对这些问题. 在面对这种问题时, ",
"一般来讲, 我们都必须务必慎重的考虑考虑. ",
"要想清楚, x, 到底是一种怎么样的存在. ",
"了解清楚x到底是一种怎么样的存在, 是解决一切问题的关键.",
"就我个人来说, x对我的意义, 不能不说非常重大. ",
"本人也是经过了深思熟虑,在每个日日夜夜思考这个问题. ",
"x, 发生了会如何, 不发生又会如何. ",
"在这种困难的抉择下, 本人思来想去, 寝食难安.",
"生活中, 若x出现了, 我们就不得不考虑它出现了的事实. ",
"这种事实对本人来说意义重大, 相信对这个世界也是有一定意义的.",
"我们都知道, 只要有意义, 那么就必须慎重考虑.",
"既然如此, ",
"那么, ",
"我认为, ",
"一般来说, ",
"总结的来说, ",
"既然如何, ",
"经过上述讨论, ",
"这样看来, ",
"从这个角度来看, ",
"我们不妨可以这样来想: ",
"这是不可避免的. ",
"可是,即使是这样,x的出现仍然代表了一定的意义. ",
"x似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实. ",
"在这种不可避免的冲突下,我们必须解决这个问题. ",
"对我个人而言,x不仅仅是一个重大的事件,还可能会改变我的人生. "
],
"after": [
"这不禁令我深思. ",
"带着这句话, 我们还要更加慎重的审视这个问题: ",
"这启发了我. ",
"我希望诸位也能好好地体会这句话. ",
"这句话语虽然很短, 但令我浮想联翩. ",
"这句话看似简单,但其中的阴郁不禁让人深思. ",
"这句话把我们带到了一个新的维度去思考这个问题: ",
"这似乎解答了我的疑惑. "
],
"before": [
"曾经说过",
"在不经意间这样说过",
"说过一句著名的话",
"曾经提到过",
"说过一句富有哲理的话"
]
}