Newer
Older
Twilight / src / main / kotlin / net / taehui / twilight / system / TVSystem.kt
@Taehui Taehui on 6 Nov 3 KB 2023-11-06 오후 7:15
package net.taehui.twilight.system

import net.taehui.twilight.Logger
import org.openqa.selenium.By
import org.openqa.selenium.TimeoutException
import org.openqa.selenium.WebDriver
import org.openqa.selenium.edge.EdgeDriver
import org.openqa.selenium.edge.EdgeOptions
import org.openqa.selenium.support.ui.ExpectedConditions
import org.openqa.selenium.support.ui.WebDriverWait
import java.time.Duration
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit

object TVSystem : Logger {
    class TVItem(val href: String, val title: String, val text: String) {
        override fun hashCode(): Int {
            return href.hashCode()
        }

        override fun equals(other: Any?): Boolean {
            return href == (other as TVItem).href
        }

        override fun toString(): String {
            return text
        }
    }

    private val ses: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor {
        Executors.defaultThreadFactory().newThread(it).apply {
            isDaemon = true
        }
    }
    private var targetSystem: WebDriver? = null

    fun handleSystem() {
        if (Configure.mode.tv) {
            try {
                targetSystem = EdgeDriver(EdgeOptions().apply {
                    addArguments("--headless", "--no-sandbox")
                })

                val pendingElements = mutableMapOf<TVItem, Int>()
                var lastElements = emptySet<TVItem>()
                ses.scheduleWithFixedDelay({
                    targetSystem?.get("https://www.twitch.tv/directory/game/Qwilight")
                    val dataTest = By.cssSelector("[data-test-selector=TitleAndChannel]")
                    val elements = try {
                        WebDriverWait(
                            targetSystem,
                            Duration.ofSeconds(1)
                        ).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(dataTest))
                        targetSystem?.findElements(dataTest) ?: throw TimeoutException()
                    } catch (e: TimeoutException) {
                        emptyList()
                    }.map {
                        TVItem(
                            it.getAttribute("href"),
                            it.findElement(By.tagName("h3")).text,
                            it.findElement(By.tagName("p")).text
                        )
                    }.toSet()
                    elements.subtract(lastElements).filter {
                        pendingElements.remove(it) == null
                    }.forEach {
                        SiteHandler.putSiteYell(it)
                    }
                    lastElements.subtract(elements).forEach {
                        pendingElements[it] = 0
                    }
                    pendingElements.toMap().forEach {
                        if (it.value < 5) {
                            pendingElements[it.key] = it.value + 1
                        } else {
                            pendingElements.remove(it.key)
                        }
                    }
                    lastElements = elements
                }, 0L, 1L, TimeUnit.MINUTES)
            } catch (e: Throwable) {
                logFault(e)
            }
        }
    }

    fun dispose() {
        ses.shutdown()
        ses.awaitTermination(1, TimeUnit.SECONDS)
        targetSystem?.quit()
    }
}