oracle-manager/src/main/kotlin/OracleNetworkExtension.kt

411 lines
16 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package net.lamgc.scext.oraclemanager
import com.oracle.bmc.core.VirtualNetworkClient
import com.oracle.bmc.core.model.CreatePublicIpDetails
import com.oracle.bmc.core.model.CreateVcnDetails
import com.oracle.bmc.core.model.Vcn
import com.oracle.bmc.core.requests.*
import com.oracle.bmc.model.BmcException
import mu.KotlinLogging
import net.lamgc.scalabot.extension.BotExtensionFactory
import org.telegram.abilitybots.api.bot.BaseAbilityBot
import org.telegram.abilitybots.api.objects.Reply
import org.telegram.abilitybots.api.util.AbilityExtension
import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageReplyMarkup
import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText
import java.io.File
class OracleNetworkExtensionFactory : BotExtensionFactory {
override fun createExtensionInstance(bot: BaseAbilityBot, shareDataFolder: File): AbilityExtension {
return OracleNetworkExtension(bot)
}
}
@Suppress("unused")
class OracleNetworkExtension(private val bot: BaseAbilityBot) : AbilityExtension {
fun networkMenu(): Reply = callbackQueryOf("oc_network_menu") { bot, upd ->
val keyboardBuilder = InlineKeyboardGroupBuilder()
.rowButton {
text("VCN 列表")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_list"))
}
.newRow()
.addButton {
text("IPv4 管理")
callbackData(upd.callbackQuery.callbackData.next("oc_network_ipv4pub_manage"))
}
.addButton {
text("IPv6 管理")
callbackData(upd.callbackQuery.callbackData.next("oc_network_ipv4pub_manage"))
}
.then()
.addBackButton(upd.callbackQuery.callbackData.next("oc_account_manager"))
EditMessageReplyMarkup.builder()
.chatId(upd.callbackQuery.message.chatId.toString())
.messageId(upd.callbackQuery.message.messageId)
.replyMarkup(keyboardBuilder.build())
.build()
.execute(bot.silent())
}
fun listVCNs(): Reply = callbackQueryOf("oc_network_vcn_list") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val vcns = client.listVcns(
ListVcnsRequest.builder()
.compartmentId(profile.tenantId)
.build()
).items
vcns.removeIf { it.lifecycleState == Vcn.LifecycleState.Terminated }
val keyboardBuilder = InlineKeyboardGroupBuilder()
for (vcn in vcns) {
logger.debug { "VCN: $vcn" }
keyboardBuilder.rowButton {
text(vcn.displayName)
callbackData(upd.callbackQuery.callbackData.next(
newAction = "oc_network_vcn_manage",
newExtraData = jsonObjectOf {
JsonFields.VcnId += vcn.id
JsonFields.VcnDisplayName += vcn.displayName
}
))
}
}
keyboardBuilder.rowButton {
text("*** 新建 VCN ***")
callbackData(
upd.callbackQuery.callbackData.next(
newAction = "oc_network_vcn_create"
)
)
}
keyboardBuilder.addBackButton(upd.callbackQuery.callbackData.next("oc_account_manager"))
EditMessageText.builder()
.chatId(upd.callbackQuery.message.chatId.toString())
.messageId(upd.callbackQuery.message.messageId)
.replyMarkup(keyboardBuilder.build())
.text(
"""
Oracle 账号 ${profile.name} 有以下 VCN
""".trimIndent()
)
.build()
.execute(bot.sender())
}
fun createVcn(): Reply = callbackQueryHandleOf("oc_network_vcn_create") {
val profile = getProfileByCallback(callbackData)
val createVcnRequest = CreateVcnRequest.builder()
.createVcnDetails(
CreateVcnDetails.builder()
.compartmentId(profile.tenantId)
.build()
)
.build()
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
// 使用 try 代码块包括 client 请求
try {
val vcn = client.createVcn(createVcnRequest).vcn
EditMessageText.builder()
.chatId(chatId)
.messageId(upd.callbackQuery.message.messageId)
.text("创建 VCN ${vcn.displayName} 成功!")
.replyMarkup(
InlineKeyboardGroupBuilder().addBackButton(callbackData.next("oc_network_vcn_list")).build()
)
.build()
.execute(bot.sender())
} catch (e: BmcException) {
EditMessageText.builder()
.chatId(chatId)
.messageId(upd.callbackQuery.message.messageId)
.text("创建 VCN 失败!\n错误信息:${e.message}")
.replyMarkup(
InlineKeyboardGroupBuilder().addBackButton(callbackData.next("oc_network_vcn_list")).build()
)
.build()
.execute(bot.sender())
}
}
fun manageVcn(): Reply = callbackQueryOf("oc_network_vcn_manage") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val vcnId = upd.callbackQuery.callbackData.extraData[JsonFields.VcnId].asString
val vcn = try {
client.getVcn(
GetVcnRequest.builder()
.vcnId(vcnId)
.build()
).vcn
} catch (e: Exception) {
logger.error(e) { "获取 VCN 信息时发生错误." }
bot.silent().send("获取 VCN 信息时发生错误,请重试一次。", upd.callbackQuery.message.chatId)
return@callbackQueryOf
}
val keyboardGroup = InlineKeyboardGroupBuilder()
.rowButton {
text("子网列表")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_subnet_list"))
}
.newRow()
.addButton {
text("网络安全组")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_nsg_manage"))
}
.addButton {
text("安全列表")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_sl_manage"))
}
.then()
.rowButton {
text("设置")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_edit"))
}
EditMessageText.builder()
.chatId(upd.callbackQuery.message.chatId.toString())
.messageId(upd.callbackQuery.message.messageId)
.replyMarkup(
keyboardGroup.addBackButton(
callback = upd.callbackQuery.callbackData.next("oc_network_vcn_list")
).build()
)
.text(
"""
--------- [ VCN ] ---------
${vcn.displayName}
状态:${vcn.lifecycleState}
私有 IPv4 段:${vcn.cidrBlock}(共 ${vcn.cidrBlocks.size} 段)
IPv6 段:${vcn.ipv6CidrBlocks.firstOrNull()}(共 ${vcn.ipv6CidrBlocks.size} 段)
""".trimIndent()
)
.build().execute(bot)
}
fun listSubnet(): Reply = callbackQueryOf("oc_network_vcn_subnet_list") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val vcnId = upd.callbackQuery.callbackData.extraData[JsonFields.VcnId].asString
val vcnDisplayName = upd.callbackQuery.callbackData.extraData[JsonFields.VcnDisplayName].asString
val subnets = client.listSubnets(
ListSubnetsRequest.builder()
.compartmentId(profile.tenantId)
.vcnId(vcnId)
.build()
).items
val keyboardBuilder = InlineKeyboardGroupBuilder()
for (subnet in subnets) {
keyboardBuilder.rowButton {
text("${subnet.displayName}${subnet.cidrBlock}")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_subnet_edit",
newExtraData = jsonObjectOf {
JsonFields.SubnetId += subnet.id
}
))
}
}
EditMessageText.builder()
.chatId(upd.callbackQuery.message.chatId.toString())
.messageId(upd.callbackQuery.message.messageId)
.replyMarkup(
keyboardBuilder.addBackButton(
callback = upd.callbackQuery.callbackData.next("oc_network_vcn_manage")
).build()
)
.text("VCN $vcnDisplayName 有以下子网Subnet)")
.build().execute(bot)
}
fun editSubnet(): Reply = callbackQueryOf("oc_network_vcn_subnet_edit") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val subnetId = upd.callbackQuery.callbackData.extraData[JsonFields.SubnetId].asString
val subnet = client.getSubnet(GetSubnetRequest.builder().subnetId(subnetId).build()).subnet
val keyboardGroup = InlineKeyboardGroupBuilder()
.newRow()
.addButton {
text("私网 IPv4")
callbackData(upd.callbackQuery.callbackData.next("oc_network_subnet_ipv4pri_manage"))
}
.then()
.rowButton {
text("IPv6")
callbackData(upd.callbackQuery.callbackData.next("oc_network_subnet_ipv6_manage"))
}
.rowButton {
text("绑定网络安全组")
callbackData(upd.callbackQuery.callbackData.next("oc_network_subnet_bind_nsg"))
}
.rowButton {
text("设置")
callbackData(upd.callbackQuery.callbackData.next("oc_network_subnet_edit"))
}
EditMessageText.builder()
.chatId(upd.callbackQuery.message.chatId.toString())
.messageId(upd.callbackQuery.message.messageId)
.replyMarkup(
keyboardGroup.addBackButton(
callback = upd.callbackQuery.callbackData.next("oc_network_vcn_subnet_list")
).build()
)
.text(
"""
${subnet.displayName}
私有 IPv4 段:${subnet.cidrBlock}
IPv6 段:${subnet.ipv6CidrBlock}
已激活安全列表数:${subnet.securityListIds.size}
所属 VCN 名称:${upd.callbackQuery.callbackData.extraData[JsonFields.VcnDisplayName].asString}
""".trimIndent()
)
.build().execute(bot)
}
fun listSubnetPublicIpv4(): Reply = callbackQueryOf("oc_network_ipv4pub_manage") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val publicIps = client.listPublicIps(
ListPublicIpsRequest.builder()
.compartmentId(profile.tenantId)
.scope(ListPublicIpsRequest.Scope.Region)
.build()
).items
val keyboardBuilder = InlineKeyboardGroupBuilder()
for (publicIp in publicIps) {
keyboardBuilder.rowButton {
text("${publicIp.displayName}${publicIp.ipAddress}")
callbackData(
upd.callbackQuery.callbackData.next("oc_network_vcn_ipv4pub_edit",
newExtraData = jsonObjectOf {
JsonFields.PublicIpId += publicIp.id
})
)
}
}
keyboardBuilder.rowButton {
text("*** 新建公网 IP ***")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_ipv4pub_add"))
}.addBackButton(
callback = upd.callbackQuery.callbackData.next("oc_network_vcn_subnet_edit")
)
EditMessageText.builder()
.replyTo(upd.callbackQuery)
.text("Oracle账号 ${profile.name} 当前区域有以下预留的公共 IP")
.replyMarkup(keyboardBuilder.build())
.build().execute(bot)
}
fun createNewIpv4Public(): Reply = callbackQueryOf("oc_network_vcn_ipv4pub_add") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val newPublicIp = try {
client.createPublicIp(
CreatePublicIpRequest.builder()
.createPublicIpDetails(
CreatePublicIpDetails.builder()
.compartmentId(profile.tenantId)
.lifetime(CreatePublicIpDetails.Lifetime.Reserved)
.build()
)
.build()
).publicIp
} catch (e: BmcException) {
logger.error(e) { "请求创建 PublicIp 时发生错误." }
bot.silent().send("创建 Ip 时发生错误。\n${e.message}", upd.callbackQuery.message.chatId)
return@callbackQueryOf
}
EditMessageText.builder()
.replyTo(upd.callbackQuery)
.text("已创建新的保留公共 IP${newPublicIp.ipAddress}")
.replyMarkup(
InlineKeyboardGroupBuilder()
.addBackButton(upd.callbackQuery.callbackData.next("oc_network_ipv4pub_manage"))
.build()
)
.build().execute(bot)
}
fun editIpv4Public(): Reply = callbackQueryOf("oc_network_vcn_ipv4pub_edit") { bot, upd ->
val profile = getProfileByCallback(upd.callbackQuery.callbackData)
val client = VirtualNetworkClient(profile.getAuthenticationDetailsProvider())
val publicIp = client.getPublicIp(
GetPublicIpRequest.builder()
.publicIpId(upd.callbackQuery.callbackData.extraData[JsonFields.PublicIpId].asString)
.build()
).publicIp
val keyboardBuilder = InlineKeyboardGroupBuilder()
.rowButton {
text("更改显示名称")
callbackData("EMPTY")
}
.rowButton {
text("删除 IP 地址")
callbackData("EMPTY")
}
.addBackButton(upd.callbackQuery.callbackData.next("oc_network_ipv4pub_manage"))
EditMessageText.builder()
.replyTo(upd.callbackQuery)
.replyMarkup(keyboardBuilder.build())
.text(
"""
---------- [ 公共 IP ] ----------
${publicIp.displayName}
IP 地址:${publicIp.ipAddress}
当前状态:${publicIp.lifecycleState}
可用范围:${publicIp.scope}
可用域:${publicIp.availabilityDomain}
""".trimIndent()
)
.build().execute(bot)
}
fun editVcn(): Reply = callbackQueryOf("oc_network_vcn_edit") { bot, upd ->
val keyboardBuilder = InlineKeyboardGroupBuilder()
.rowButton {
text("更改名称")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_change_name"))
}
.rowButton {
text("删除 VCN")
callbackData(upd.callbackQuery.callbackData.next("oc_network_vcn_delete"))
}
EditMessageReplyMarkup.builder()
.chatId(upd.callbackQuery.message.chatId.toString())
.messageId(upd.callbackQuery.message.messageId)
.replyMarkup(
keyboardBuilder.addBackButton(
callback = upd.callbackQuery.callbackData.next("oc_network_vcn_manage")
).build()
)
.build().execute(bot)
}
companion object {
private val logger = KotlinLogging.logger { }
}
}