working checker
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -43,3 +43,4 @@ bin/
 | 
			
		||||
 | 
			
		||||
### Mac OS ###
 | 
			
		||||
.DS_Store
 | 
			
		||||
/chromedriver.log
 | 
			
		||||
 
 | 
			
		||||
@@ -1,56 +0,0 @@
 | 
			
		||||
package net.xintanalabs.rssotto.config
 | 
			
		||||
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriver
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriverService
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeOptions
 | 
			
		||||
import org.springframework.context.annotation.Bean
 | 
			
		||||
import org.springframework.context.annotation.Configuration
 | 
			
		||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter
 | 
			
		||||
import org.springframework.web.client.RestTemplate
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
@Configuration
 | 
			
		||||
class AppConfig {
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun restTemplate(): RestTemplate {
 | 
			
		||||
        return RestTemplate()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun json(): Json {
 | 
			
		||||
        return Json {
 | 
			
		||||
            ignoreUnknownKeys = true
 | 
			
		||||
            coerceInputValues = true
 | 
			
		||||
            prettyPrint = true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun additionalMessageConverters(json: Json): List<KotlinSerializationJsonHttpMessageConverter> {
 | 
			
		||||
        return listOf(KotlinSerializationJsonHttpMessageConverter(json))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean(destroyMethod = "quit")
 | 
			
		||||
    fun chromeDriver(): ChromeDriver {
 | 
			
		||||
        // Set log file to suppress console output (optional)
 | 
			
		||||
        val logFile = File("chromedriver.log")
 | 
			
		||||
        val service = ChromeDriverService.Builder()
 | 
			
		||||
            .withLogFile(logFile) // Redirect logs to a file
 | 
			
		||||
            .withSilent(true) // Suppress console output
 | 
			
		||||
            .withVerbose(false) // Explicitly disable verbose logging
 | 
			
		||||
            .build()
 | 
			
		||||
 | 
			
		||||
        // Optional: Set hideCommandPromptWindow for Windows
 | 
			
		||||
        System.setProperty("webdriver.chrome.hideCommandPromptWindow", "true")
 | 
			
		||||
 | 
			
		||||
        val options = ChromeOptions().apply {
 | 
			
		||||
            addArguments("--headless")
 | 
			
		||||
            addArguments("--disable-gpu")
 | 
			
		||||
            addArguments("--no-sandbox")
 | 
			
		||||
            addArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124")
 | 
			
		||||
        }
 | 
			
		||||
        return ChromeDriver(service, options)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +1,62 @@
 | 
			
		||||
package net.xintanalabs.rssotto
 | 
			
		||||
package net.xintanalabs.rssotto.config
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties
 | 
			
		||||
import org.springframework.boot.context.properties.bind.ConstructorBinding
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriver
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriverService
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeOptions
 | 
			
		||||
import org.springframework.context.annotation.Bean
 | 
			
		||||
import org.springframework.context.annotation.Configuration
 | 
			
		||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter
 | 
			
		||||
import org.springframework.web.client.RestTemplate
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import org.springframework.web.reactive.function.client.WebClient
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
@ConfigurationProperties(prefix = "version-checker")
 | 
			
		||||
data class ApplicationConfig(
 | 
			
		||||
    val intervalMinutes: Int
 | 
			
		||||
)
 | 
			
		||||
@Configuration
 | 
			
		||||
class ApplicationConfig {
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun restTemplate(): RestTemplate {
 | 
			
		||||
        return RestTemplate()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun json(): Json {
 | 
			
		||||
        return Json {
 | 
			
		||||
            ignoreUnknownKeys = true
 | 
			
		||||
            coerceInputValues = true
 | 
			
		||||
            prettyPrint = true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun webClient(builder: WebClient.Builder): WebClient {
 | 
			
		||||
        return builder.build()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun additionalMessageConverters(json: Json): List<KotlinSerializationJsonHttpMessageConverter> {
 | 
			
		||||
        return listOf(KotlinSerializationJsonHttpMessageConverter(json))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Bean(destroyMethod = "quit")
 | 
			
		||||
    fun chromeDriver(): ChromeDriver {
 | 
			
		||||
        // Set log file to suppress console output (optional)
 | 
			
		||||
        val logFile = File("chromedriver.log")
 | 
			
		||||
        val service = ChromeDriverService.Builder()
 | 
			
		||||
            .withLogFile(logFile) // Redirect logs to a file
 | 
			
		||||
            .withSilent(true) // Suppress console output
 | 
			
		||||
            .withVerbose(false) // Explicitly disable verbose logging
 | 
			
		||||
            .build()
 | 
			
		||||
 | 
			
		||||
        // Optional: Set hideCommandPromptWindow for Windows
 | 
			
		||||
        System.setProperty("webdriver.chrome.hideCommandPromptWindow", "true")
 | 
			
		||||
 | 
			
		||||
        val options = ChromeOptions().apply {
 | 
			
		||||
            addArguments("--headless")
 | 
			
		||||
            addArguments("--disable-gpu")
 | 
			
		||||
            addArguments("--no-sandbox")
 | 
			
		||||
            addArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124")
 | 
			
		||||
        }
 | 
			
		||||
        return ChromeDriver(service, options)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
package net.xintanalabs.rssotto
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
@ConfigurationProperties(prefix = "version-checker")
 | 
			
		||||
data class ApplicationConfigProperties(
 | 
			
		||||
    val intervalMinutes: Int
 | 
			
		||||
)
 | 
			
		||||
@@ -2,8 +2,10 @@ package net.xintanalabs.rssotto
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.autoconfigure.SpringBootApplication
 | 
			
		||||
import org.springframework.boot.runApplication
 | 
			
		||||
import org.springframework.scheduling.annotation.EnableScheduling
 | 
			
		||||
 | 
			
		||||
@SpringBootApplication
 | 
			
		||||
@EnableScheduling
 | 
			
		||||
class RssotoApplication
 | 
			
		||||
 | 
			
		||||
fun main(args: Array<String>) {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,8 @@ import org.springframework.web.reactive.function.client.awaitExchange
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
class ApiChecker(private val webClient: WebClient) : IVersionChecker {
 | 
			
		||||
    override suspend fun getLatestVersion(paramsDict: Map<String, String>, source: Source): String {
 | 
			
		||||
        val url = paramsDict["url"]?.takeIf { it.isNotEmpty() }
 | 
			
		||||
    override suspend fun getLatestVersion(paramsDict: Map<String, String>): String {
 | 
			
		||||
       val url = paramsDict["url"]?.takeIf { it.isNotEmpty() }
 | 
			
		||||
            ?: throw IllegalArgumentException("API URL required")
 | 
			
		||||
        val jsonPath = paramsDict["jsonPath"]?.takeIf { it.isNotEmpty() }
 | 
			
		||||
            ?: throw IllegalArgumentException("jsonPath required")
 | 
			
		||||
 
 | 
			
		||||
@@ -3,5 +3,5 @@ package net.xintanalabs.rssotto.components.checkers
 | 
			
		||||
import net.xintanalabs.rssotto.model.Source
 | 
			
		||||
 | 
			
		||||
interface IVersionChecker {
 | 
			
		||||
    suspend fun getLatestVersion(paramsDict: Map<String, String>, source: Source): String
 | 
			
		||||
    suspend fun getLatestVersion(paramsDict: Map<String, String>): String
 | 
			
		||||
}
 | 
			
		||||
@@ -1,70 +0,0 @@
 | 
			
		||||
package net.xintanalabs.rssotto.components.checkers
 | 
			
		||||
 | 
			
		||||
import kotlinx.coroutines.*
 | 
			
		||||
import net.xintanalabs.rssotto.ApplicationConfig
 | 
			
		||||
import net.xintanalabs.rssotto.model.App
 | 
			
		||||
import net.xintanalabs.rssotto.model.CheckerType
 | 
			
		||||
import net.xintanalabs.rssotto.model.Source
 | 
			
		||||
import net.xintanalabs.rssotto.services.AppService
 | 
			
		||||
import net.xintanalabs.rssotto.services.CheckerTypeService
 | 
			
		||||
import net.xintanalabs.rssotto.services.SourceService
 | 
			
		||||
import org.slf4j.LoggerFactory
 | 
			
		||||
import org.springframework.scheduling.annotation.Async
 | 
			
		||||
import org.springframework.scheduling.annotation.Scheduled
 | 
			
		||||
import org.springframework.stereotype.Component
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
class VersionCheckTask(
 | 
			
		||||
    private val config: ApplicationConfig,
 | 
			
		||||
    private val appService: AppService,
 | 
			
		||||
    private val  sourceService: SourceService,
 | 
			
		||||
    private val checkerTypeService: CheckerTypeService
 | 
			
		||||
    //private val versionService: VersionService
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    private val logger = LoggerFactory.getLogger(VersionCheckTask::class.java)
 | 
			
		||||
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
 | 
			
		||||
 | 
			
		||||
    //@Scheduled(fixedRateString = "\${version-checker.interval-minutes}000", initialDelay = 1000)
 | 
			
		||||
    //@Async
 | 
			
		||||
    fun checkVersions() {
 | 
			
		||||
        scope.launch {
 | 
			
		||||
            val apps: List<App> = appService.getAllApps()
 | 
			
		||||
            var sources: List<Source> = sourceService.getAllSources()
 | 
			
		||||
            var checkerTypes: List<CheckerType> = checkerTypeService.getAllCheckerTypes()
 | 
			
		||||
            logger.info("Starting version check task for ${apps.size} sources")
 | 
			
		||||
            apps.map { app ->
 | 
			
		||||
                // async {
 | 
			
		||||
                    // try {
 | 
			
		||||
                        /*
 | 
			
		||||
                        val source: Source? = sources.find { s -> s.id == app.source }
 | 
			
		||||
                        if (source != null) {
 | 
			
		||||
                            val checkerType: CheckerType? = checkerTypes.find { ct -> ct.id == source.checkerType }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                            app.params
 | 
			
		||||
                            val params = mutableMapOf<String, String>()
 | 
			
		||||
                            app.url.let { params["url"] = it }
 | 
			
		||||
                            app.jsonPath?.let { params["jsonPath"] = it }
 | 
			
		||||
                            app.regex?.let { params["regex"] = it }
 | 
			
		||||
                            app.mode?.let { params["mode"] = it }
 | 
			
		||||
 | 
			
		||||
                            val sourceDef = SourceDef(
 | 
			
		||||
                                defaults = mapOf(
 | 
			
		||||
                                    "regex" to (app.regex ?: ""),
 | 
			
		||||
                                    "mode" to (app.mode ?: "default")
 | 
			
		||||
                                )
 | 
			
		||||
                            )
 | 
			
		||||
 | 
			
		||||
                            val version = versionService.checkVersion(app.type, params, sourceDef)
 | 
			
		||||
                            logger.info("Version for ${app.url} (${app.type}): $version")*/
 | 
			
		||||
                            // Optionally save to DB (if using JPA)
 | 
			
		||||
                        }
 | 
			
		||||
                    //} catch (e: Exception) {
 | 
			
		||||
                        //logger.error("Failed to check version for ${app.url}: ${e.message}", e)
 | 
			
		||||
                    //}
 | 
			
		||||
                // }
 | 
			
		||||
            // }.awaitAll()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,38 +0,0 @@
 | 
			
		||||
package net.xintanalabs.rssotto.components.checkers
 | 
			
		||||
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriver
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriverService
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeOptions
 | 
			
		||||
import org.springframework.context.annotation.Bean
 | 
			
		||||
import org.springframework.context.annotation.Configuration
 | 
			
		||||
import org.springframework.web.client.RestTemplate
 | 
			
		||||
import org.springframework.web.reactive.function.client.WebClient
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
@Configuration
 | 
			
		||||
class WebConfig {
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun restTemplate(): RestTemplate = RestTemplate()
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun webClient(): WebClient = WebClient.builder().build()
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun chromeDriver(): ChromeDriver {
 | 
			
		||||
        val logFile = File("chromedriver.log")
 | 
			
		||||
        val service = ChromeDriverService.Builder()
 | 
			
		||||
            .withLogFile(logFile) // Redirect logs to a file
 | 
			
		||||
            .withSilent(true) // Suppress console output
 | 
			
		||||
            .withVerbose(false) // Explicitly disable verbose logging
 | 
			
		||||
            .build()
 | 
			
		||||
 | 
			
		||||
        val options = ChromeOptions().apply {
 | 
			
		||||
            addArguments("--headless")
 | 
			
		||||
            addArguments("--disable-gpu")
 | 
			
		||||
            addArguments("--no-sandbox")
 | 
			
		||||
            addArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ChromeDriver(service, options)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,9 @@ package net.xintanalabs.rssotto.components.checkers.scrape
 | 
			
		||||
import kotlinx.coroutines.delay
 | 
			
		||||
import net.xintanalabs.rssotto.components.checkers.IVersionChecker
 | 
			
		||||
import net.xintanalabs.rssotto.model.Source
 | 
			
		||||
import net.xintanalabs.rssotto.tasks.ScheduledTasks
 | 
			
		||||
import org.openqa.selenium.chrome.ChromeDriver
 | 
			
		||||
import org.slf4j.LoggerFactory
 | 
			
		||||
import org.springframework.stereotype.Component
 | 
			
		||||
import org.springframework.web.client.RestTemplate
 | 
			
		||||
import java.util.regex.Pattern
 | 
			
		||||
@@ -13,31 +15,29 @@ class ScrapeChecker(
 | 
			
		||||
    private val restTemplate: RestTemplate,
 | 
			
		||||
    private val chromeDriver: ChromeDriver
 | 
			
		||||
) : IVersionChecker {
 | 
			
		||||
    override suspend fun getLatestVersion(paramsDict: Map<String, String>, source: Source): String {
 | 
			
		||||
 | 
			
		||||
    private val log = LoggerFactory.getLogger(ScrapeChecker::class.java)
 | 
			
		||||
 | 
			
		||||
    override suspend fun getLatestVersion(paramsDict: Map<String, String>): String {
 | 
			
		||||
        val url = paramsDict["url"]?.takeIf { it.isNotEmpty() }
 | 
			
		||||
            ?: throw IllegalArgumentException("URL required")
 | 
			
		||||
 | 
			
		||||
        val mode = getValueOrDefault(paramsDict, "mode", source)
 | 
			
		||||
        log.info("Url : {}", url)
 | 
			
		||||
        val mode = paramsDict["mode"]
 | 
			
		||||
        log.info("Mode : {}", mode)
 | 
			
		||||
        val fetcher: IScrapeFetcher = when (mode) {
 | 
			
		||||
            "selenium" -> SeleniumFetcher(chromeDriver)
 | 
			
		||||
            "jsoup" -> JSoupFetcher()
 | 
			
		||||
            else -> DefaultScrapeFetcher(restTemplate)
 | 
			
		||||
        }
 | 
			
		||||
        val response = fetcher.fetch(url)
 | 
			
		||||
 | 
			
		||||
        val cleanedResponse = response.replace(">\\s+<".toRegex(), "><")
 | 
			
		||||
        val regex = getValueOrDefault(paramsDict, "regex", source)
 | 
			
		||||
 | 
			
		||||
        log.info("Response : {}", cleanedResponse)
 | 
			
		||||
        val regex = paramsDict["regex"]
 | 
			
		||||
        log.info("Regex : {}", regex)
 | 
			
		||||
        val match = Pattern.compile(regex).matcher(cleanedResponse)
 | 
			
		||||
        if (!match.find() || match.groupCount() < 1) {
 | 
			
		||||
            throw Exception("No match with regex in response")
 | 
			
		||||
        }
 | 
			
		||||
        return match.group(1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getValueOrDefault(dict: Map<String, String>, key: String, source: Source): String {
 | 
			
		||||
        return dict[key]?.takeIf { it.isNotEmpty() }
 | 
			
		||||
            ?: source.defaults[key]
 | 
			
		||||
            ?: ""
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,33 @@
 | 
			
		||||
package net.xintanalabs.rssotto.controller
 | 
			
		||||
 | 
			
		||||
import net.xintanalabs.rssotto.constants.Constants
 | 
			
		||||
import net.xintanalabs.rssotto.services.AppService
 | 
			
		||||
import net.xintanalabs.rssotto.services.CheckerTypeService
 | 
			
		||||
import net.xintanalabs.rssotto.services.LatestVersionFinderService
 | 
			
		||||
import net.xintanalabs.rssotto.services.SourceService
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("${Constants.API_BASE_PATH_V0}/exec")
 | 
			
		||||
class LatestVersionFinderController(
 | 
			
		||||
    private val latestVersionFinderService: LatestVersionFinderService,
 | 
			
		||||
    private val appService: AppService,
 | 
			
		||||
    private val sourceService: SourceService,
 | 
			
		||||
    private val checkerTypeService: CheckerTypeService
 | 
			
		||||
    ) {
 | 
			
		||||
    @PostMapping("/version-check")
 | 
			
		||||
    suspend fun executeVersionCheck(): String? {
 | 
			
		||||
        return try {
 | 
			
		||||
            val apps = appService.getAllApps()
 | 
			
		||||
            val sources = sourceService.getAllSources()
 | 
			
		||||
            val checkerTypes = checkerTypeService.getAllCheckerTypes()
 | 
			
		||||
            latestVersionFinderService.getAllLatestAppVersions(apps,sources, checkerTypes)
 | 
			
		||||
 | 
			
		||||
            "ok"
 | 
			
		||||
        } catch(e: Exception) {
 | 
			
		||||
            e.message
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -14,11 +14,19 @@ import org.springframework.web.bind.annotation.RestController
 | 
			
		||||
class SourceController(private val sourceService: SourceService) {
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    suspend fun createSource(@RequestBody source: Source): Source {
 | 
			
		||||
        return sourceService.createSource(source)
 | 
			
		||||
        return try {
 | 
			
		||||
            sourceService.createSource(source)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            throw RuntimeException(e.message, e)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping
 | 
			
		||||
    suspend fun getAllSources(): List<Source> {
 | 
			
		||||
        return sourceService.getAllSources()
 | 
			
		||||
        return try {
 | 
			
		||||
            sourceService.getAllSources()
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            throw RuntimeException(e.message, e)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,11 +2,13 @@ package net.xintanalabs.rssotto.model
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonInclude
 | 
			
		||||
import org.springframework.data.annotation.Id
 | 
			
		||||
import org.springframework.data.mongodb.core.mapping.Field
 | 
			
		||||
 | 
			
		||||
@JsonInclude(JsonInclude.Include.NON_NULL)
 | 
			
		||||
data class Source(
 | 
			
		||||
    @Id val id: String? = null,
 | 
			
		||||
    val name: String,
 | 
			
		||||
    @Field("type")
 | 
			
		||||
    val checkerType: String,
 | 
			
		||||
    val defaults: Map<String, String> = mapOf()
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,72 @@
 | 
			
		||||
package net.xintanalabs.rssotto.services
 | 
			
		||||
 | 
			
		||||
import net.xintanalabs.rssotto.components.checkers.CheckerFactory
 | 
			
		||||
import net.xintanalabs.rssotto.components.checkers.IVersionChecker
 | 
			
		||||
import net.xintanalabs.rssotto.components.checkers.scrape.ScrapeChecker
 | 
			
		||||
import net.xintanalabs.rssotto.model.App
 | 
			
		||||
import net.xintanalabs.rssotto.model.CheckerType
 | 
			
		||||
import net.xintanalabs.rssotto.model.Source
 | 
			
		||||
import org.slf4j.LoggerFactory
 | 
			
		||||
import org.springframework.stereotype.Service
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
class LatestVersionFinderService(private val checkerFactory: CheckerFactory) {
 | 
			
		||||
    private val log = LoggerFactory.getLogger(LatestVersionFinderService::class.java)
 | 
			
		||||
 | 
			
		||||
    suspend fun getLatestAppVersion(app: App, sources: List<Source>, checkerTypes: List<CheckerType>): String? {
 | 
			
		||||
        val source: Source? = sources.find { s -> s.id == app.source }
 | 
			
		||||
        var appVersion: String? = null
 | 
			
		||||
        if (source != null) {
 | 
			
		||||
            val checkerType: CheckerType? = checkerTypes.find { ct -> ct.id == source.checkerType }
 | 
			
		||||
 | 
			
		||||
            if (checkerType != null) {
 | 
			
		||||
                val checker: IVersionChecker = checkerFactory.createChecker(checkerType.name)
 | 
			
		||||
                val paramsMap: Map<String, String> = mapOf<String, String>(
 | 
			
		||||
                    "url" to  getUrl(app, source),
 | 
			
		||||
                    "regex" to  getRegex(app, source),
 | 
			
		||||
                    "mode" to getMode(app, source)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                appVersion = checker.getLatestVersion(paramsMap)
 | 
			
		||||
                log.info("App (${app.name}, latest versión ${appVersion}")
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return appVersion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    suspend fun getAllLatestAppVersions(
 | 
			
		||||
        apps: List<App>,
 | 
			
		||||
        sources: List<Source>,
 | 
			
		||||
        checkerTypes: List<CheckerType>
 | 
			
		||||
    ): Map<String, String?> {
 | 
			
		||||
        val versionsMap: MutableMap<String, String?> = mutableMapOf<String, String?>()
 | 
			
		||||
        apps.map { app ->
 | 
			
		||||
            if (app.id !== null) {
 | 
			
		||||
                val appLatestVersion: String? = getLatestAppVersion(app, sources, checkerTypes)
 | 
			
		||||
                versionsMap[app.id] = appLatestVersion
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return versionsMap
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getValue(field: String, app: App, source: Source): String {
 | 
			
		||||
        var value: String? = app.params[field]
 | 
			
		||||
        if (value == null) {
 | 
			
		||||
            value = source.defaults[field]
 | 
			
		||||
        }
 | 
			
		||||
        return value ?: ""
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getMode(app: App, source: Source): String {
 | 
			
		||||
        return getValue("mode", app, source)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getUrl(app: App, source: Source): String {
 | 
			
		||||
        return getValue("url", app, source)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getRegex(app: App, source: Source): String {
 | 
			
		||||
        return getValue("regex", app, source)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
package net.xintanalabs.rssotto.tasks
 | 
			
		||||
 | 
			
		||||
import org.slf4j.LoggerFactory
 | 
			
		||||
import org.springframework.scheduling.annotation.Scheduled
 | 
			
		||||
import org.springframework.stereotype.Component
 | 
			
		||||
import java.text.SimpleDateFormat
 | 
			
		||||
import java.util.Date
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
class ScheduledTasks {
 | 
			
		||||
    private val log = LoggerFactory.getLogger(ScheduledTasks::class.java)
 | 
			
		||||
    private val dateFormat = SimpleDateFormat("HH:mm:ss")
 | 
			
		||||
 | 
			
		||||
    @Scheduled(fixedRate = 500000)
 | 
			
		||||
    fun reportCurrentTime() {
 | 
			
		||||
        log.info("The time is now {}", dateFormat.format(Date()))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user