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

xyz.cssxsh.mirai.arknights.ArknightsCollector.kt Maven / Gradle / Ivy

There is a newer version: 2.3.1
Show newest version
package xyz.cssxsh.mirai.arknights

import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.*
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage
import org.jsoup.nodes.*
import org.jsoup.parser.*
import org.jsoup.select.*
import xyz.cssxsh.arknights.*
import xyz.cssxsh.arknights.announce.*
import xyz.cssxsh.arknights.bilibili.*
import xyz.cssxsh.arknights.excel.*
import xyz.cssxsh.arknights.weibo.*
import xyz.cssxsh.mirai.arknights.data.*
import java.util.WeakHashMap

public class ArknightsCollector(private val contact: Contact) : FlowCollector {
    internal companion object {
        val cache = HashMap>().withDefault { WeakHashMap() }
        val mutex: Mutex = Mutex()
    }

    /**
     * 推送 [value] 到 [contact]
     */
    override suspend fun emit(value: CacheInfo): Unit = mutex.withLock {
        val history = cache.getOrPut(contact.id) { WeakHashMap() }
        if (value.url in history) return
        val message = when (value) {
            // 微博
            is MicroBlog -> {
                val accept = ArknightsTaskConfig.blog[contact.id] ?: return
                if (accept.none { it.uid == value.user.id }) return
                buildMessageChain {
                    appendLine("鹰角有新微博!@${value.user.name}")

                    append(blog = value)

                    value.retweeted?.let { retweeted ->
                        appendLine()
                        appendLine("----------------")
                        appendLine("@${retweeted.user.name}")

                        append(blog = retweeted)
                    }
                }
            }
            // 公告
            is Announcement -> {
                val accept = ArknightsTaskConfig.announce[contact.id] ?: return
                if (accept.none { it == value.type }) return
                buildMessageChain {
                    appendLine("鹰角有新公告!${value.title}")
                    append(announcement = value)
                }
            }
            // 视频
            is Video -> {
                val accept = ArknightsTaskConfig.video[contact.id] ?: return
                if (accept.none { value.type in it.sub }) return
                buildMessageChain {
                    appendLine("鹰角有新视频!${value.title}")
                    append(video = value)
                }
            }
            // 周常
            is WeeklyClock -> {
                val accept = ArknightsTaskConfig.weekly[contact.id] ?: return
                if (value.weekly.type !in accept) return
                buildMessageChain {
                    appendLine("方舟周常 ${value.zone.title} 今天开启")
                    appendLine("有需要的材料记得刷哦")
                }
            }
            // 未实现的类型
            else -> {
                logger.error { "未实现的推送 ${value::class.qualifiedName}" }
                return
            }
        }
        contact.sendMessage(message)
        history[value.url] = System.currentTimeMillis()
    }

    private fun parseNodes(html: String, baseUri: String): List {
        val body = Parser.htmlParser().parseInput(html, baseUri).body()
        val visitor = object : NodeVisitor, MutableList by ArrayList() {
            override fun head(node: Node, depth: Int) {
                if (node is TextNode) add(node)
            }

            override fun tail(node: Node, depth: Int) {
                if (node is Element) add(node)
            }
        }
        NodeTraversor.traverse(visitor, body)

        return visitor
    }

    private suspend fun MessageChainBuilder.append(blog: MicroBlog): MessageChainBuilder = apply {
        appendLine("时间: ${blog.created}")
        appendLine("链接: ${blog.url}")
        val content = try {
            ArknightsSubscriber.blogs.content(blog = blog)
        } catch (cause: Exception) {
            logger.warning({ "加载[${blog.url}]长微博失败" }, cause)
            blog.raw ?: blog.text
        }
        for (node in parseNodes(content, blog.url)) {
            when (node) {
                is TextNode -> append(node.wholeText)
                is Element -> when (node.nodeName()) {
                    // 图片
                    "img" -> {
                        append("[图片]")
                    }
                    // 链接
                    "a" -> {
                        when {
                            node.text() == node.attr("href").trim() -> Unit
                            node.childrenSize() > 0 -> Unit
                            else -> append("<${node.attr("href")}>")
                        }
                    }
                    // 换行
                    "br", "p" -> {
                        append("\n")
                    }
                }
                // 忽略未知
                else -> continue
            }
        }

        try {
            val images = ArknightsSubscriber.blogs.images(blog = blog)
            for (file in images) {
                append(file.uploadAsImage(contact))
            }
        } catch (cause: Exception) {
            logger.warning({ "下载微博图片失败" }, cause)
        }
    }

    private suspend fun MessageChainBuilder.append(announcement: Announcement): MessageChainBuilder = apply {
        appendLine("日期: ${announcement.created.toLocalDate()}")
        appendLine("分类: ${announcement.group}")
        appendLine("链接: ${announcement.url}")
        val html = ArknightsSubscriber.announcements.download(announcement.url)
        for (node in parseNodes(html.readText(), announcement.url)) {
            when (node) {
                is TextNode -> append(node.wholeText.trim())
                is Element -> when (node.nodeName()) {
                    // 图片
                    "img" -> {
                        val image = try {
                            ArknightsSubscriber.announcements.download(url = node.attr("src"))
                                .uploadAsImage(contact)
                        } catch (cause: Exception) {
                            logger.warning({ "下载微博图片失败" }, cause)
                            continue
                        }
                        append(image)
                    }
                    // 链接
                    "a" -> {
                        when {
                            node.text() == node.attr("href").trim() -> Unit
                            node.childrenSize() > 0 -> Unit
                            else -> append("<${node.attr("href")}>")
                        }
                    }
                    // 换行
                    "br", "p" -> {
                        append("\n")
                    }
                }
                // 忽略未知
                else -> continue
            }
        }
    }

    private suspend fun MessageChainBuilder.append(video: Video): MessageChainBuilder = apply {
        appendLine("链接: ${video.url}")
        appendLine("时间: ${video.created}")
        if (video.description.isNotBlank()) {
            appendLine("简介:")
            appendLine(video.description)
        }

        try {
            val image = ArknightsSubscriber.videos.cover(video = video)
                .uploadAsImage(contact)
            append(image)
        } catch (cause: Exception) {
            appendLine("添加图片[${video.pic}]失败, ${cause.message}")
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy