All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xyz.cssxsh.mirai.admin.MiraiService.kt Maven / Gradle / Ivy

The newest version!
package xyz.cssxsh.mirai.admin

import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.compression.*
import net.mamoe.mirai.*
import net.mamoe.mirai.console.*
import net.mamoe.mirai.console.command.*
import net.mamoe.mirai.console.permission.*
import net.mamoe.mirai.console.plugin.*
import net.mamoe.mirai.console.plugin.jvm.*
import net.mamoe.mirai.console.util.*
import net.mamoe.mirai.console.util.ContactUtils.render
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.message.code.*
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.message.*
import net.mamoe.mirai.utils.*
import xyz.cssxsh.mirai.admin.data.*
import xyz.cssxsh.mirai.spi.*
import java.time.*
import java.util.*

internal val logger by lazy {
    try {
        MiraiAdminPlugin.logger
    } catch (_: UninitializedPropertyAccessException) {
        MiraiLogger.Factory.create(MiraiAdministrator::class)
    }
}

internal fun Bot.owner() = getFriendOrFail(AdminSetting.owner)

internal val http = HttpClient(OkHttp) {
    install(UserAgent) {
        agent = "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/045913 Mobile Safari/537.36 V1_AND_SQ_8.8.68_2538_YYB_D A_8086800 QQ/8.8.68.7265 NetType/WIFI WebP/0.3.0 Pixel/1080 StatusBarHeight/76 SimpleUISwitch/1 QQTheme/2971 InMagicWin/0 StudyMode/0 CurrentMode/1 CurrentFontScale/1.0 GlobalDensityScale/0.9818182 AppId/537112567 Edg/98.0.4758.102"
    }
    ContentEncoding()
}

internal val NormalMember.lastSpeakAt: LocalDateTime
    get() = LocalDateTime.ofInstant(Instant.ofEpochSecond(lastSpeakTimestamp.toLong()), ZoneId.systemDefault())

internal val NormalMember.joinAt: LocalDateTime
    get() = LocalDateTime.ofInstant(Instant.ofEpochSecond(joinTimestamp.toLong()), ZoneId.systemDefault())

internal suspend fun CommandSender.request(hint: String, contact: Contact? = null): MessageChain = when (this) {
    is ConsoleCommandSender -> {
        val code = MiraiConsole.requestInput(hint)
        MiraiCode.deserializeMiraiCode(code, contact)
    }
    is CommandSenderOnMessage<*> -> {
        sendMessage(hint)
        fromEvent.nextMessage()
    }
    else -> throw IllegalStateException("未知环境 $this")
}

internal fun CommandOwner.registerPermission(name: String, description: String): Permission {
    return PermissionService.INSTANCE.register(permissionId(name), description, parentPermission)
}

internal fun NewFriendRequestEvent.render(accept: Boolean): Message = buildMessageChain {
    appendLine("with <${eventId}>")
    appendLine("@${fromNick}#${fromId}")
    appendLine("申请添加好友")
    appendLine("from $fromGroup")
    appendLine(message)
    if (accept) appendLine("已自动同意")
}

internal fun MemberJoinRequestEvent.render(accept: Boolean): Message = buildMessageChain {
    appendLine("with <${eventId}>")
    appendLine("@${fromNick}#${fromId}")
    appendLine("申请加入群")
    appendLine("to [$groupName](${groupId}) by $invitorId")
    appendLine(message)
    if (accept) appendLine("已自动同意")
}

internal fun BotInvitedJoinGroupRequestEvent.render(accept: Boolean): Message = buildMessageChain {
    appendLine("with <${eventId}>")
    appendLine("@${invitorNick}#${invitorId}")
    appendLine("邀请机器人加入群")
    appendLine("to [${groupName}](${groupId})")
    if (accept) appendLine("已自动同意")
}

internal fun AdminRequestEventData.render(): String = buildString {
    for ((qq, list) in this@render) {
        if (list.isEmpty()) continue
        val bot = try {
            Bot.getInstance(qq).render()
        } catch (_: NoSuchElementException) {
            "Bot($qq)"
        }
        appendLine("--- $bot ---")
        for (request in list) {
            appendLine(request)
        }
    }
    if (isEmpty()) {
        appendLine("没有记录")
    }
}

internal fun ComparableService.Loader.reload() {
    instances.clear()
    val current = Thread.currentThread()
    val oc = current.contextClassLoader
    try {
        for (plugin in PluginManager.plugins) {
            if (plugin !is JvmPlugin) continue
            if (plugin.description.dependencies.none { it.id == "xyz.cssxsh.mirai.plugin.mirai-administrator" }) continue
            val classLoader = plugin::class.java.classLoader
            current.contextClassLoader = classLoader
            for (provider in ServiceLoader.load(ComparableService::class.java, classLoader).stream()) {
                try {
                    val service = provider.get()
                    instances.add(service)
                } catch (cause: ServiceConfigurationError) {
                    logger.warning({ "${provider.type().name} load fail." }, cause)
                }
            }
        }
    } finally {
        current.contextClassLoader = oc
    }
    instances.add(MiraiAutoApprover)
    instances.add(MiraiOnlineMessage)
    instances.add(MiraiStatusMessage)
    instances.add(MiraiMemberCleaner)
    instances.add(MiraiCurfewTimer)
    instances.add(MiraiContentCensor)
    instances.add(MiraiBlackList)
    instances.add(MiraiMessageTimer)
    instances.add(MiraiBackupService)
}

internal fun ComparableService.Loader.render(): String = buildString {
    appendLine("ComparableService Registered [${instances.size}]:")
    for (subclass in ComparableService::class.sealedSubclasses) {
        appendLine("${subclass.simpleName}: ${registered(subclass.java).joinToString { it.id }}")
    }
}

internal fun target(contact: Contact): MessageSource? {
    for (handler in ComparableService()) {
        return try {
            handler.target(contact = contact) ?: continue
        } catch (cause: Exception) {
            logger.warning({ "message source find failure." }, cause)
            continue
        }
    }
    return null
}

internal fun from(member: Member): MessageSource? {
    for (handler in ComparableService()) {
        return try {
            handler.from(member = member) ?: continue
        } catch (cause: Exception) {
            logger.warning({ "message source find failure." }, cause)
            continue
        }
    }
    return null
}

internal fun quote(event: MessageEvent): MessageSource? {
    for (handler in ComparableService()) {
        return try {
            handler.quote(event = event) ?: continue
        } catch (cause: Exception) {
            logger.warning({ "message source find failure." }, cause)
            continue
        }
    }
    return null
}

internal fun backup() {
    if (ComparableService().isEmpty()) throw UnsupportedOperationException("没有任何实例")
    for (backup in ComparableService()) {
        try {
            backup.bot()
        } catch (cause: UnsupportedOperationException) {
            continue
        } catch (cause: Exception) {
            logger.warning({ "backup bot failure." }, cause)
            continue
        }
        logger.info { "backup bot ok by ${backup.id}" }
        break
    }

    for (backup in ComparableService()) {
        try {
            backup.friend()
        } catch (cause: UnsupportedOperationException) {
            continue
        } catch (cause: Exception) {
            logger.warning({ "backup friend failure." }, cause)
            continue
        }
        logger.info { "backup friend ok by ${backup.id}" }
        break
    }

    for (backup in ComparableService()) {
        try {
            backup.group()
        } catch (cause: UnsupportedOperationException) {
            continue
        } catch (cause: Exception) {
            logger.warning({ "backup group failure." }, cause)
            continue
        }
        logger.info { "backup group ok by ${backup.id}" }
        break
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy