Converted utility classes to objects

This commit is contained in:
Erik C. Thauvin 2023-02-03 00:02:55 -08:00
parent b61fed0fa6
commit 2a17c42737
10 changed files with 130 additions and 142 deletions

View file

@ -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

View file

@ -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")

10
pom.xml
View file

@ -10,7 +10,7 @@
<artifactId>jokeapi</artifactId>
<version>0.9-SNAPSHOT</version>
<name>jokeapi</name>
<description>Kotlin/Java Wrapper for Sv443's JokeAPI</description>
<description>Wrapper for Sv443's JokeAPI</description>
<url>https://github.com/ethauvin/jokeapi</url>
<licenses>
<license>
@ -27,8 +27,8 @@
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/ethauvin/jokeapi.git</connection>
<developerConnection>scm:git:git@github.com:ethauvin/jokeapi.git</developerConnection>
<connection>scm:git://github.com/ethauvin/jokeapi.git</connection>
<developerConnection>scm:git@github.com:ethauvin/jokeapi.git</developerConnection>
<url>https://github.com/ethauvin/jokeapi</url>
</scm>
<issueManagement>
@ -40,7 +40,7 @@
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-bom</artifactId>
<version>1.7.20</version>
<version>1.8.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -50,7 +50,7 @@
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.7.20</version>
<version>1.8.0</version>
<scope>compile</scope>
</dependency>
<dependency>

View file

@ -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<String, String> = 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<String, String> = 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<Joke> {
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<Joke> {
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
)
}
}

View file

@ -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)
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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<JSONException> { parseError(JSONObject("{}")) }