diff --git a/VERSION b/VERSION index 0d91a54..1d0ba9e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.0 +0.4.0 diff --git a/build.gradle.kts b/build.gradle.kts index 20d8dba..2835257 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ buildscript { plugins { id("com.github.johnrengelman.shadow") version Libs.com_github_johnrengelman_shadow_gradle_plugin - kotlin("jvm") + kotlin("jvm") version "2.1.10" application } @@ -44,8 +44,8 @@ dependencies { implementation(Libs.swagger_core) implementation(Libs.swagger_ui) implementation(Libs.slack_api_model_kotlin_extension) - implementation(Libs.fuel) - implementation(Libs.fuel_jackson) + implementation(Libs.ktor_client_cio) + implementation(Libs.ktor_client_core) testImplementation(Libs.junit_jupiter) } @@ -54,9 +54,9 @@ application { mainClass.set("com.anthonycicchetti.slackbot.MainKt") } -kotlin { - jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(17)) +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 7e540e1..741bd01 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,16 +12,11 @@ buildscript { } } -plugins { - `kotlin-dsl` -} repositories { mavenCentral() } -kotlin { - jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } -} \ No newline at end of file +plugins { + `kotlin-dsl` +} diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt index 2ac6563..f698581 100644 --- a/buildSrc/src/main/kotlin/Libs.kt +++ b/buildSrc/src/main/kotlin/Libs.kt @@ -9,7 +9,7 @@ import kotlin.String * $ ./gradlew refreshVersions * And edit the file `versions.properties` * - * See https://github.com/jmfayard/refreshVersions + * See https://github.com/Splitties/refreshVersions */ public object Libs { public const val jackson_databind: String = "com.fasterxml.jackson.core:jackson-databind:_" @@ -20,10 +20,6 @@ public object Libs { public const val com_github_johnrengelman_shadow_gradle_plugin: String = "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:_" - public const val fuel: String = "com.github.kittinunf.fuel:fuel:_" - - public const val fuel_jackson: String = "com.github.kittinunf.fuel:fuel-jackson:_" - public const val slack_api_model_kotlin_extension: String = "com.slack.api:slack-api-model-kotlin-extension:_" @@ -34,8 +30,23 @@ public object Libs { public const val javalin_openapi: String = "io.javalin:javalin-openapi:_" + public const val ktor_client_cio: String = "io.ktor:ktor-client-cio:_" + + public const val ktor_client_core: String = "io.ktor:ktor-client-core:_" + public const val swagger_core: String = "io.swagger.core.v3:swagger-core:_" + public const val org_jetbrains_kotlin_jvm_gradle_plugin: String = + "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:_" + + public const val kotlin_build_tools_impl: String = + "org.jetbrains.kotlin:kotlin-build-tools-impl" + + public const val kotlin_scripting_compiler_embeddable: String = + "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:_" + + public const val kotlin_stdlib_jdk8: String = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:_" + public const val junit_jupiter: String = "org.junit.jupiter:junit-jupiter:_" public const val slf4j_simple: String = "org.slf4j:slf4j-simple:_" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..249e583 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c68..e382118 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index c53aefa..a69d9cb 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..53a6b23 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/settings.gradle.kts b/settings.gradle.kts index 9529ec6..06786df 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,7 @@ pluginManagement { gradlePluginPortal() } plugins { - id("de.fayard.refreshVersions") version "0.40.2" + id("de.fayard.refreshVersions") version "0.60.5" } } diff --git a/slackbot.iml b/slackbot.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/slackbot.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt b/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt index a79e0fd..e25de66 100644 --- a/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt +++ b/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt @@ -1,6 +1,8 @@ package com.anthonycicchetti.slackbot -import com.anthonycicchetti.slackbot.osrs.ItemMapper +import com.anthonycicchetti.slackbot.osrs.ApiItem +import com.anthonycicchetti.slackbot.osrs.getOsrsItemPrice +import com.anthonycicchetti.slackbot.osrs.getOsrsItemByName import com.anthonycicchetti.slackbot.utility.* import io.javalin.http.Context import io.javalin.Javalin @@ -12,6 +14,7 @@ import io.javalin.plugin.openapi.ui.SwaggerOptions import io.swagger.v3.oas.models.OpenAPI import io.swagger.v3.oas.models.info.Info import io.swagger.v3.oas.models.servers.Server +import kotlinx.coroutines.runBlocking import org.slf4j.LoggerFactory import java.util.* import kotlin.math.roundToInt @@ -67,13 +70,15 @@ fun main() { it.description = "Accepts an OSRS item name and searches for its prices on the wiki" it.summary = "POST for OSRS Price" }.body().json("200")) { ctx -> - logger.info("OSRS Item: Received request for ${ctx.body()}") - val item = ItemMapper.getItemByName(ctx.body()) - if (item == null) { - ctx.json(notFoundItem) - } else { - val itemPrices = ItemMapper.getItemPrice(item) - ctx.json((BlockResponse(200, item.name, itemPrices.high, itemPrices.low))) + runBlocking { + logger.info("OSRS Item: Received request for ${ctx.body()}") + val item: ApiItem? = getOsrsItemByName(ctx.body()) + if (item == null) { + ctx.json(notFoundItem) + } else { + val itemPrices = getOsrsItemPrice(item) + ctx.json((BlockResponse(200, item.name, itemPrices.high, itemPrices.low))) + } } }) } @@ -124,24 +129,28 @@ private fun sendResponse(ctx: Context, respObj: RespObj) { Commands.Spongebob -> { put("text", respObj.text.toSpongemock()); put("response_type", "in_channel") } + Commands.Uppercase -> { put("text", respObj.text.uppercase(Locale.getDefault())); put("response_type", "in_channel") } + Commands.Claptext -> { put("text", respObj.text.toClapText()); put("response_type", "in_channel") } - Commands.OsrsItem -> { - val item = ItemMapper.getItemByName(respObj.text) + + Commands.OsrsItem -> runBlocking { + val item = getOsrsItemByName(respObj.text) val itemPricesBlock: BlockResponse = if (item == null) { notFoundItem } else { - val itemPrices = ItemMapper.getItemPrice(item) + val itemPrices = getOsrsItemPrice(item) BlockResponse(200, item.name, itemPrices.high, itemPrices.low) } val logger = LoggerFactory.getLogger("sendResponse") - logger.info("${itemPricesBlock.response}") + logger.info(itemPricesBlock.response) put("blocks", itemPricesBlock.response); put("response_type", "in_channel") } + Commands.Error -> { put("text", respObj.text); put("response_type", "ephemeral") } diff --git a/src/main/kotlin/com/anthonycicchetti/slackbot/osrs/ItemMapper.kt b/src/main/kotlin/com/anthonycicchetti/slackbot/osrs/ItemMapper.kt index 4912caa..842790d 100644 --- a/src/main/kotlin/com/anthonycicchetti/slackbot/osrs/ItemMapper.kt +++ b/src/main/kotlin/com/anthonycicchetti/slackbot/osrs/ItemMapper.kt @@ -3,57 +3,64 @@ package com.anthonycicchetti.slackbot.osrs import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue -import com.github.kittinunf.fuel.Fuel -import com.github.kittinunf.result.Result +import io.ktor.client.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.client.call.* +import io.ktor.client.engine.cio.* +import io.ktor.client.plugins.* +import kotlinx.coroutines.* +import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.nio.charset.Charset -class ItemMapper { - companion object { - private val logger = LoggerFactory.getLogger("ItemMapper") - private val mapper = ObjectMapper() - fun getItemByName(itemName: String): ApiItem? = - itemList.firstOrNull { item -> item.name.lowercase() == itemName.lowercase() } +val logger: Logger by lazy { LoggerFactory.getLogger("ItemMapper") } +val mapper: ObjectMapper by lazy { ObjectMapper() } - fun getItemPrice(item: ApiItem): Item { - val response = Fuel.get("https://prices.runescape.wiki/api/v1/osrs/latest", listOf("id" to item.id)) - .appendHeader("User-Agent", "private_slackbot - @AnthonyCicc") - .responseString(Charset.defaultCharset()).third - return when (response) { - is Result.Success -> { - val r: Resp = mapper.readValue(response.get()) - r.data.getOrDefault(item.id.toString(), Item()) - } - is Result.Failure -> { - logger.warn("Couldn't find Item with ID ${item.id}") - Item() - } - } +val client = HttpClient(CIO) { + install(UserAgent) { + agent = "private_slackbot - @AnthonyCicc" + } +} + +suspend fun getItemList(): List { + val response = client.get("https://prices.runescape.wiki/api/v1/osrs/mapping") + return when (response.status.value) { + in 200..299 -> { + logger.info("Got item mappings") + mapper.readValue(response.bodyAsText()) } - private val itemList: List = run { - val response = Fuel.get("https://prices.runescape.wiki/api/v1/osrs/mapping") - .appendHeader("User-Agent", "private_slackbot - @AnthonyCicc") - .responseString(Charset.defaultCharset()).third - when (response) { - is Result.Success -> { - logger.info("Got item mappings") - mapper.readValue(response.get()) - } - is Result.Failure -> { - logger.info("Could not get item mappings") - emptyList() - } - } + else -> { + logger.info("Could not get item mappings") + emptyList() } } } -data class Resp( +suspend fun getOsrsItemByName(itemName: String): ApiItem? = + getItemList().firstOrNull { item: ApiItem -> item.name.lowercase() == itemName.lowercase() } + +suspend fun getOsrsItemPrice(item: ApiItem): Item { + val response = client + .get("https://prices.runescape.wiki/api/v1/osrs/latest") + return when (response.status.value) { + in 200..299 -> { + val r: Resp = mapper.readValue(response.body()) + r.data.getOrDefault(item.id.toString(), Item()) + } + + else -> { + logger.warn("Couldn't find Item with ID ${item.id}") + Item() + } + } +} + +private data class Resp( val data: Map = emptyMap(), ) -data class Item ( +data class Item( val low: Int = 0, val lowTime: Long = 0L, val high: Int = 0, diff --git a/versions.properties b/versions.properties index 93b067c..1518a52 100644 --- a/versions.properties +++ b/versions.properties @@ -1,5 +1,5 @@ #### Dependencies and Plugin versions with their available updates. -#### Generated by `./gradlew refreshVersions` version 0.40.2 +#### Generated by `./gradlew refreshVersions` version 0.60.5 #### #### Don't manually edit or split the comments that start with four hashtags (####), #### they will be overwritten by refreshVersions. @@ -7,36 +7,77 @@ #### suppress inspection "SpellCheckingInspection" for whole file #### suppress inspection "UnusedProperty" for whole file -plugin.com.github.johnrengelman.shadow=7.1.2 +plugin.com.github.johnrengelman.shadow=8.1.1 -plugin.de.fayard.buildSrcLibs=0.40.2 +plugin.de.fayard.buildSrcLibs=0.60.5 -plugin.org.gradle.kotlin.kotlin-dsl=2.4.1 +plugin.org.gradle.kotlin.kotlin-dsl=5.1.2 +## # available=5.2.0 -version.com.fasterxml.jackson.core..jackson-databind=2.13.3 +version.com.fasterxml.jackson.core..jackson-databind=2.18.2 -version.com.fasterxml.jackson.module..jackson-module-kotlin=2.13.3 +version.com.fasterxml.jackson.module..jackson-module-kotlin=2.18.2 -version.com.github.kittinunf.fuel..fuel-jackson=2.3.1 +version.com.slack.api..slack-api-model-kotlin-extension=1.45.2 -version.com.github.kittinunf.fuel..fuel=2.3.1 +version.io.javalin..javalin=4.6.8 +## # available=5.0.0.RC0 +## # available=5.0.0.RC1 +## # available=5.0.0.RC2 +## # available=5.0.0 +## # available=5.0.1 +## # available=5.1.0 +## # available=5.1.1 +## # available=5.1.2 +## # available=5.1.3 +## # available=5.1.4 +## # available=5.2.0 +## # available=5.3.0 +## # available=5.3.1 +## # available=5.3.2 +## # available=5.4.0 +## # available=5.4.1 +## # available=5.4.2 +## # available=5.5.0 +## # available=5.6.0 +## # available=5.6.1 +## # available=5.6.2 +## # available=5.6.3 +## # available=5.6.4 +## # available=5.6.5 +## # available=6.0.0-beta.1 +## # available=6.0.0-beta.2 +## # available=6.0.0-beta.3 +## # available=6.0.0-beta.4 +## # available=6.0.0 +## # available=6.0.1 +## # available=6.1.0 +## # available=6.1.1 +## # available=6.1.2 +## # available=6.1.3 +## # available=6.1.4 +## # available=6.1.6 +## # available=6.2.0 +## # available=6.3.0 +## # available=6.4.0 -version.com.slack.api..slack-api-model-kotlin-extension=1.24.0 +version.io.javalin..javalin-openapi=4.6.8 -version.io.javalin..javalin=4.6.4 - -version.io.javalin..javalin-openapi=4.6.4 - -version.io.swagger.core.v3..swagger-core=2.2.2 +version.io.swagger.core.v3..swagger-core=2.2.28 ## unused version.junit=5.8.2 -version.junit.jupiter=5.8.2 -## # available=5.9.0-M1 -## # available=5.9.0-RC1 +version.junit.jupiter=5.11.4 +## # available=5.12.0-M1 +## # available=5.12.0-RC1 +## # available=5.12.0-RC2 -version.kotlin=1.7.10 +version.kotlin=2.1.10 +## # available=2.1.20-Beta1 +## # available=2.1.20-Beta2 + +version.ktor=3.1.0 version.org.slf4j..slf4j-simple=1.7.36 ## # available=1.8.0-alpha0 @@ -54,5 +95,60 @@ version.org.slf4j..slf4j-simple=1.7.36 ## # available=2.0.0-alpha5 ## # available=2.0.0-alpha6 ## # available=2.0.0-alpha7 +## # available=2.0.0-beta0 +## # available=2.0.0-beta1 +## # available=2.0.0 +## # available=2.0.1 +## # available=2.0.2 +## # available=2.0.3 +## # available=2.0.4 +## # available=2.0.5 +## # available=2.0.6 +## # available=2.0.7 +## # available=2.0.8 +## # available=2.0.9 +## # available=2.0.10 +## # available=2.0.11 +## # available=2.0.12 +## # available=2.0.13 +## # available=2.0.14 +## # available=2.0.15 +## # available=2.0.16 +## # available=2.1.0-alpha0 +## # available=2.1.0-alpha1 -version.org.webjars..swagger-ui=4.11.1 +version.org.webjars..swagger-ui=4.19.1 +## # available=5.0.0 +## # available=5.1.0 +## # available=5.1.2 +## # available=5.1.3 +## # available=5.2.0 +## # available=5.3.1 +## # available=5.4.2 +## # available=5.5.0 +## # available=5.6.1 +## # available=5.7.2 +## # available=5.9.0 +## # available=5.10.3 +## # available=5.11.8 +## # available=5.11.9 +## # available=5.11.10 +## # available=5.12.0 +## # available=5.12.2 +## # available=5.13.0 +## # available=5.14.0 +## # available=5.15.0 +## # available=5.15.1 +## # available=5.15.2 +## # available=5.15.2-1 +## # available=5.17.0 +## # available=5.17.1 +## # available=5.17.2 +## # available=5.17.6 +## # available=5.17.7 +## # available=5.17.11 +## # available=5.17.14 +## # available=5.18.0 +## # available=5.18.1 +## # available=5.18.2 +## # available=5.18.3