BiliInviteCode/src/main/kotlin/cc/maxmc/invite/command/InviteCodeCommands.kt

204 lines
8.3 KiB
Kotlin

package cc.maxmc.invite.command
import cc.maxmc.invite.PluginScope
import cc.maxmc.invite.concurrent.chatInput
import cc.maxmc.invite.data.InviteCode
import cc.maxmc.invite.data.InviteCodes
import cc.maxmc.invite.listener.InvitedListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.bukkit.Bukkit
import org.bukkit.command.ConsoleCommandSender
import org.bukkit.entity.Player
import org.jetbrains.exposed.sql.transactions.transaction
import taboolib.common.platform.command.CommandBuilder
import taboolib.common.platform.command.command
import taboolib.common.platform.function.getDataFolder
import taboolib.common.platform.function.info
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
object InviteCodeCommands {
init {
command("inviteCode", aliases = listOf("code", "icode", "ic")) {
cmdUse()
cmdGenerate()
cmdEdit()
cmdAdd()
cmdRemove()
cmdCurrent()
}
}
private fun CommandBuilder.CommandComponent.cmdUse() = literal("use") {
tailrec suspend fun requireQQNumber(player: Player): String? {
val input = chatInput(player, "§e| §7请输入您的QQ号进行绑定 (输入 §ecancel §7取消)")
if (input == "cancel") return null
if (input.length >= 10) return requireQQNumber(player)
if (input.toLongOrNull() == null) return requireQQNumber(player)
return input
}
dynamic {
execute<Player> { sender, _, argument ->
if (!InvitedListener.cache.containsKey(sender.uniqueId)) return@execute sender.sendMessage("§e| §7您的账号已激活, 无需使用邀请码.")
sender.sendMessage("§b| §7正在激活邀请码...")
PluginScope.launch {
val inviteCode = transaction {
val inviteCode = InviteCode.find { InviteCodes.inviteCode eq argument }.firstOrNull()
?: return@transaction let { sender.sendMessage("§c| §7该激活码不存在, 请重试."); null }
if (inviteCode.name != null) return@transaction sender.sendMessage("§c| §7该邀请码已被激活, 请重试.")
.let { null }
return@transaction inviteCode
} ?: return@launch
val qqNum = requireQQNumber(sender) ?: return@launch sender.sendMessage("§e| §7已取消激活验证码.")
sender.sendMessage("§a| §7该激活码成功绑定至QQ: §a${qqNum}")
InvitedListener.cache.remove(sender.uniqueId)
transaction {
inviteCode.run {
name = sender.name
uid = sender.uniqueId
qq = qqNum
}
sender.sendMessage("§a| §7成功激活邀请码.")
}
}
}
}
}
private fun CommandBuilder.CommandComponent.cmdGenerate() = literal("generate") {
fun generateRandomString(length: Int): String {
val availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
val result = StringBuilder()
repeat(length) {
result.append(availableChars.random())
}
return result.toString()
}
tailrec fun generateAvailableCode(): String {
val result = "${generateRandomString(5)}-${generateRandomString(5)}-${generateRandomString(5)}-${
generateRandomString(5)
}"
val exist = transaction {
val exist = !InviteCode.find { InviteCodes.inviteCode eq result }.empty()
if (!exist) {
InviteCode.new {
inviteCode = result
}
}
return@transaction exist
}
return if (exist) generateAvailableCode() else result
}
val format = SimpleDateFormat("yyyy-MM-dd")
dynamic {
restrict<ConsoleCommandSender> { _, _, arg ->
return@restrict arg.toIntOrNull() != null
}
execute<ConsoleCommandSender> { _, _, arg ->
PluginScope.launch {
info("§b| §7正在生成邀请码...")
val generated = ArrayList<String>()
repeat(arg.toInt()) {
generated.add(generateAvailableCode())
}
val generateFolder = File(getDataFolder(), "generated")
generateFolder.mkdirs()
val count = generateFolder.listFiles()!!.filter {
it.name.startsWith(format.format(Date()))
}.size
val target = File(generateFolder, "${format.format(Date())}-${count + 1}.txt")
withContext(Dispatchers.IO) {
target.createNewFile()
target.writeText(generated.joinToString("\n"))
}
info("§a| §7成功生成 §a$arg §7个邀请码")
}
}
}
}
private fun CommandBuilder.CommandComponent.cmdEdit() = literal("edit") {
dynamic {
restrict<ConsoleCommandSender> { _, _, arg ->
!InviteCode.find { InviteCodes.name eq arg }.empty()
}
suggestion<ConsoleCommandSender> { sender, ctx ->
return@suggestion Bukkit.getOnlinePlayers().map { it.name }
}
dynamic {
restrict<ConsoleCommandSender> { _, _, arg ->
arg.length <= 10 && arg.toLongOrNull() != null
}
execute<ConsoleCommandSender> { sender, ctx, arg ->
PluginScope.launch {
InviteCode.find { InviteCodes.name eq ctx.get(-1) }.first().run {
qq = arg
}
sender.sendMessage("§a| §7修改成功")
}
}
}
}
}
private fun CommandBuilder.CommandComponent.cmdAdd() = literal("add") {
dynamic {
execute<ConsoleCommandSender> { sender, _, arg ->
PluginScope.launch {
if (!InviteCode.find { InviteCodes.inviteCode eq arg }.empty()) {
sender.sendMessage("§c| §7该邀请码已存在, 无法添加.")
return@launch
}
InviteCode.new {
inviteCode = arg
}
sender.sendMessage("§a| §7成功添加一个邀请码: §a$arg")
}
}
}
}
private fun CommandBuilder.CommandComponent.cmdRemove() = literal("remove") {
execute<ConsoleCommandSender> { sender, _, arg ->
PluginScope.launch {
transaction {
val findings = InviteCode.find { InviteCodes.inviteCode eq arg }
if (findings.empty()) {
sender.sendMessage("§e| §7该邀请码不存在, 无需删除.")
}
findings.first().delete()
sender.sendMessage("§a| §7成功删除该邀请码.")
}
}
}
}
private fun CommandBuilder.CommandComponent.cmdCurrent() = literal("current") {
execute<ConsoleCommandSender> { sender, _, _ ->
PluginScope.launch {
val codes = ArrayList<String>(2000)
transaction {
InviteCode.find { InviteCodes.uid eq null }.forEach {
codes.add(it.inviteCode)
}
}
val result = codes.joinToString("\n")
val output = File(getDataFolder(), "current.txt")
withContext(Dispatchers.IO) {
output.mkdirs()
output.createNewFile()
output.writeText(result)
}
sender.sendMessage("现存可用邀请码已保存至plugins/BiliInviteCode/current.txt")
}
}
}
}