diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5881074..7b57c8d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,6 +1,6 @@ name: gradle-ci -on: [push, pull_request, workflow_dispatch] +on: [ push, pull_request, workflow_dispatch ] jobs: build: @@ -15,13 +15,14 @@ jobs: java-version: [ 11, 17, 18 ] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: + distribution: 'zulu' java-version: ${{ matrix.java-version }} - name: Grant execute permission for gradlew @@ -29,33 +30,20 @@ jobs: - name: Cache SonarCloud packages if: matrix.java-version == env.SONAR_JDK - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ matrix.java-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle-${{ matrix.java-version }}- - - name: Test with Gradle - run: ./gradlew build check --stacktrace + uses: gradle/gradle-build-action@v2 + with: + arguments: build check --stacktrace - name: SonarCloud if: success() && matrix.java-version == env.SONAR_JDK env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: ./gradlew sonarqube - - - name: Cleanup Gradle Cache - run: | - rm -f ~/.gradle/caches/modules-2/modules-2.lock - rm -f ~/.gradle/caches/modules-2/gc.properties + run: ./gradlew sonar --info diff --git a/build.gradle.kts b/build.gradle.kts index 9808282..86bdcdf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ import org.jetbrains.dokka.gradle.DokkaTask import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("com.github.ben-manes.versions") version "0.44.0" + id("com.github.ben-manes.versions") version "0.45.0" id("io.gitlab.arturbosch.detekt") version "1.22.0" id("java") id("maven-publish") diff --git a/pom.xml b/pom.xml index 76f3c72..d314f31 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ jokeapi 0.9-SNAPSHOT jokeapi - Kotlin/Java Wrapper for Sv443's JokeAPI + Wrapper for Sv443's JokeAPI https://github.com/ethauvin/jokeapi @@ -27,8 +27,8 @@ - scm:git:git://github.com/ethauvin/jokeapi.git - scm:git:git@github.com:ethauvin/jokeapi.git + scm:git://github.com/ethauvin/jokeapi.git + scm:git@github.com:ethauvin/jokeapi.git https://github.com/ethauvin/jokeapi @@ -40,7 +40,7 @@ org.jetbrains.kotlin kotlin-bom - 1.7.20 + 1.8.0 pom import @@ -50,7 +50,7 @@ org.jetbrains.kotlin kotlin-stdlib-jdk8 - 1.7.20 + 1.8.0 compile diff --git a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeApi.kt b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeApi.kt index a5cfb3f..22f20a1 100644 --- a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeApi.kt +++ b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeApi.kt @@ -50,121 +50,119 @@ import java.util.stream.Collectors /** * Implements the [Sv443's JokeAPI](https://jokeapi.dev/). */ -class JokeApi private constructor() { - companion object { - private const val API_URL = "https://v2.jokeapi.dev/" +object JokeApi { + private const val API_URL = "https://v2.jokeapi.dev/" - @JvmStatic - val logger: Logger by lazy { Logger.getLogger(JokeApi::class.java.simpleName) } + @JvmStatic + val logger: Logger by lazy { Logger.getLogger(JokeApi::class.java.simpleName) } - /** - * Makes a direct API call. - * - * Sse the [JokeAPI Documentation](https://jokeapi.dev/#endpoints) for more details. - */ - @JvmStatic - @JvmOverloads - @Throws(HttpErrorException::class) - fun apiCall( - endPoint: String, - path: String = "", - params: Map = emptyMap(), - auth: String = "" - ): String { - val urlBuilder = StringBuilder("$API_URL$endPoint") + /** + * Makes a direct API call. + * + * Sse the [JokeAPI Documentation](https://jokeapi.dev/#endpoints) for more details. + */ + @JvmStatic + @JvmOverloads + @Throws(HttpErrorException::class) + fun apiCall( + endPoint: String, + path: String = "", + params: Map = emptyMap(), + auth: String = "" + ): String { + val urlBuilder = StringBuilder("$API_URL$endPoint") - if (path.isNotEmpty()) { - if (!urlBuilder.endsWith(('/'))) { - urlBuilder.append('/') - } - urlBuilder.append(path) + if (path.isNotEmpty()) { + if (!urlBuilder.endsWith(('/'))) { + urlBuilder.append('/') } + urlBuilder.append(path) + } - if (params.isNotEmpty()) { - urlBuilder.append('?') - val it = params.iterator() - while (it.hasNext()) { - val param = it.next() - urlBuilder.append(param.key) - if (param.value.isNotEmpty()) { - urlBuilder.append("=").append( - URLEncoder.encode(param.value, StandardCharsets.UTF_8).replace("+", "%20") - .replace("*", "%2A").replace("%7E", "~") - ) - } - if (it.hasNext()) { - urlBuilder.append("&") - } + if (params.isNotEmpty()) { + urlBuilder.append('?') + val it = params.iterator() + while (it.hasNext()) { + val param = it.next() + urlBuilder.append(param.key) + if (param.value.isNotEmpty()) { + urlBuilder.append("=").append( + URLEncoder.encode(param.value, StandardCharsets.UTF_8).replace("+", "%20") + .replace("*", "%2A").replace("%7E", "~") + ) + } + if (it.hasNext()) { + urlBuilder.append("&") } } - return fetchUrl(urlBuilder.toString(), auth) } + return fetchUrl(urlBuilder.toString(), auth) + } - /** - * Returns one or more jokes using a [configuration][JokeConfig]. - * - * See the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. - */ - @JvmStatic - @Throws(HttpErrorException::class) - fun getRawJokes(config: JokeConfig): String { - return getRawJokes( - categories = config.categories, - lang = config.language, - blacklistFlags = config.flags, - type = config.type, - format = config.format, - contains = config.contains, - idRange = config.idRange, - amount = config.amount, - safe = config.safe, - auth = config.auth - ) - } + /** + * Returns one or more jokes using a [configuration][JokeConfig]. + * + * See the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. + */ + @JvmStatic + @Throws(HttpErrorException::class) + fun getRawJokes(config: JokeConfig): String { + return getRawJokes( + categories = config.categories, + lang = config.language, + blacklistFlags = config.flags, + type = config.type, + format = config.format, + contains = config.contains, + idRange = config.idRange, + amount = config.amount, + safe = config.safe, + auth = config.auth + ) + } - /** - * Retrieve a [Joke] instance using a [configuration][JokeConfig]. - * - * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. - */ - @JvmStatic - @JvmOverloads - @Throws(HttpErrorException::class, JokeException::class) - fun getJoke(config: JokeConfig = JokeConfig.Builder().build()): Joke { - return getJoke( - categories = config.categories, - lang = config.language, - blacklistFlags = config.flags, - type = config.type, - contains = config.contains, - idRange = config.idRange, - safe = config.safe, - auth = config.auth, - splitNewLine = config.splitNewLine - ) - } + /** + * Retrieve a [Joke] instance using a [configuration][JokeConfig]. + * + * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. + */ + @JvmStatic + @JvmOverloads + @Throws(HttpErrorException::class, JokeException::class) + fun getJoke(config: JokeConfig = JokeConfig.Builder().build()): Joke { + return getJoke( + categories = config.categories, + lang = config.language, + blacklistFlags = config.flags, + type = config.type, + contains = config.contains, + idRange = config.idRange, + safe = config.safe, + auth = config.auth, + splitNewLine = config.splitNewLine + ) + } - /** - * Returns an array of [Joke] instances using a [configuration][JokeConfig]. - * - * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. - */ - @JvmStatic - @Throws(HttpErrorException::class, JokeException::class) - fun getJokes(config: JokeConfig): Array { - return getJokes( - categories = config.categories, - lang = config.language, - blacklistFlags = config.flags, - type = config.type, - contains = config.contains, - idRange = config.idRange, - amount = config.amount, - safe = config.safe, - auth = config.auth, - splitNewLine = config.splitNewLine - ) - } + /** + * Returns an array of [Joke] instances using a [configuration][JokeConfig]. + * + * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. + */ + @JvmStatic + @Throws(HttpErrorException::class, JokeException::class) + fun getJokes(config: JokeConfig): Array { + return getJokes( + categories = config.categories, + lang = config.language, + blacklistFlags = config.flags, + type = config.type, + contains = config.contains, + idRange = config.idRange, + amount = config.amount, + safe = config.safe, + auth = config.auth, + splitNewLine = config.splitNewLine + ) } } diff --git a/src/main/kotlin/net/thauvin/erik/jokeapi/util.kt b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt similarity index 96% rename from src/main/kotlin/net/thauvin/erik/jokeapi/util.kt rename to src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt index fb4c06a..9d838f8 100644 --- a/src/main/kotlin/net/thauvin/erik/jokeapi/util.kt +++ b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt @@ -1,5 +1,5 @@ /* - * util.kt + * JokeUtil.kt * * Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net) * @@ -29,6 +29,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +@file:JvmName("JokeUtil") + package net.thauvin.erik.jokeapi import net.thauvin.erik.jokeapi.exceptions.HttpErrorException @@ -52,14 +54,14 @@ internal fun fetchUrl(url: String, auth: String = ""): String { val connection = URL(url).openConnection() as HttpURLConnection connection.setRequestProperty( - "User-Agent", "Mozilla/5.0 (Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0" + "User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0" ) if (auth.isNotEmpty()) { connection.setRequestProperty("Authentication", auth) } if (connection.responseCode in 200..399) { - val body = connection.inputStream.bufferedReader().readText() + val body = connection.inputStream.bufferedReader().use { it.readText() } if (JokeApi.logger.isLoggable(Level.FINE)) { JokeApi.logger.fine(body) } diff --git a/src/test/kotlin/net/thauvin/erik/jokeapi/ApiCallTest.kt b/src/test/kotlin/net/thauvin/erik/jokeapi/ApiCallTest.kt index ed62699..c165512 100644 --- a/src/test/kotlin/net/thauvin/erik/jokeapi/ApiCallTest.kt +++ b/src/test/kotlin/net/thauvin/erik/jokeapi/ApiCallTest.kt @@ -34,7 +34,7 @@ package net.thauvin.erik.jokeapi import assertk.assertThat import assertk.assertions.isGreaterThan import assertk.assertions.startsWith -import net.thauvin.erik.jokeapi.JokeApi.Companion.apiCall +import net.thauvin.erik.jokeapi.JokeApi.apiCall import net.thauvin.erik.jokeapi.models.Format import net.thauvin.erik.jokeapi.models.Parameter import org.json.JSONObject diff --git a/src/test/kotlin/net/thauvin/erik/jokeapi/ExceptionsTest.kt b/src/test/kotlin/net/thauvin/erik/jokeapi/ExceptionsTest.kt index 7481011..b8eab48 100644 --- a/src/test/kotlin/net/thauvin/erik/jokeapi/ExceptionsTest.kt +++ b/src/test/kotlin/net/thauvin/erik/jokeapi/ExceptionsTest.kt @@ -43,7 +43,7 @@ import assertk.assertions.isNull import assertk.assertions.prop import assertk.assertions.size import assertk.assertions.startsWith -import net.thauvin.erik.jokeapi.JokeApi.Companion.logger +import net.thauvin.erik.jokeapi.JokeApi.logger import net.thauvin.erik.jokeapi.exceptions.HttpErrorException import net.thauvin.erik.jokeapi.exceptions.JokeException import net.thauvin.erik.jokeapi.models.Category diff --git a/src/test/kotlin/net/thauvin/erik/jokeapi/GetJokeTest.kt b/src/test/kotlin/net/thauvin/erik/jokeapi/GetJokeTest.kt index 636aa60..dd6b119 100644 --- a/src/test/kotlin/net/thauvin/erik/jokeapi/GetJokeTest.kt +++ b/src/test/kotlin/net/thauvin/erik/jokeapi/GetJokeTest.kt @@ -48,7 +48,7 @@ import assertk.assertions.isNotNull import assertk.assertions.isTrue import assertk.assertions.prop import assertk.assertions.size -import net.thauvin.erik.jokeapi.JokeApi.Companion.logger +import net.thauvin.erik.jokeapi.JokeApi.logger import net.thauvin.erik.jokeapi.exceptions.JokeException import net.thauvin.erik.jokeapi.models.Category import net.thauvin.erik.jokeapi.models.Flag diff --git a/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt b/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt index 4ac0237..4046eac 100644 --- a/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt +++ b/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt @@ -41,10 +41,10 @@ import assertk.assertions.isGreaterThanOrEqualTo import assertk.assertions.isTrue import assertk.assertions.prop import assertk.assertions.size -import net.thauvin.erik.jokeapi.JokeApi.Companion.getJoke -import net.thauvin.erik.jokeapi.JokeApi.Companion.getJokes -import net.thauvin.erik.jokeapi.JokeApi.Companion.getRawJokes -import net.thauvin.erik.jokeapi.JokeApi.Companion.logger +import net.thauvin.erik.jokeapi.JokeApi.getJoke +import net.thauvin.erik.jokeapi.JokeApi.getJokes +import net.thauvin.erik.jokeapi.JokeApi.getRawJokes +import net.thauvin.erik.jokeapi.JokeApi.logger import net.thauvin.erik.jokeapi.models.Category import net.thauvin.erik.jokeapi.models.Flag import net.thauvin.erik.jokeapi.models.Format diff --git a/src/test/kotlin/net/thauvin/erik/jokeapi/UtilTest.kt b/src/test/kotlin/net/thauvin/erik/jokeapi/JokeUtilTest.kt similarity index 98% rename from src/test/kotlin/net/thauvin/erik/jokeapi/UtilTest.kt rename to src/test/kotlin/net/thauvin/erik/jokeapi/JokeUtilTest.kt index cb28d1f..c61191e 100644 --- a/src/test/kotlin/net/thauvin/erik/jokeapi/UtilTest.kt +++ b/src/test/kotlin/net/thauvin/erik/jokeapi/JokeUtilTest.kt @@ -40,7 +40,7 @@ import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(BeforeAllTests::class) -internal class UtilTest { +internal class JokeUtilTest { @Test fun `Invalid JSON Error`() { assertThrows { parseError(JSONObject("{}")) }