diff --git a/.idea/misc.xml b/.idea/misc.xml index 7408350..a57f655 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -2,20 +2,8 @@ - - - - diff --git a/detekt-baseline.xml b/detekt-baseline.xml index 50acbf1..42699a3 100644 --- a/detekt-baseline.xml +++ b/detekt-baseline.xml @@ -1,12 +1,13 @@ - + - + - LongParameterList:JokeApi.kt$( amount: Int, categories: Set<Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set<Flag> = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false ) - LongParameterList:JokeApi.kt$( categories: Set<Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set<Flag> = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false ) - LongParameterList:JokeApi.kt$( categories: Set<Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set<Flag> = emptySet(), type: Type = Type.ALL, format: Format = Format.JSON, contains: String = "", idRange: IdRange = IdRange(), amount: Int = 1, safe: Boolean = false, auth: String = "" ) - LongParameterList:JokeConfig.kt$JokeConfig$( val categories: Set<Category>, val language: Language, val flags: Set<Flag>, val type: Type, val format: Format, val contains: String, val idRange: IdRange, val amount: Int, val safe: Boolean, val splitNewLine: Boolean, val auth: String ) - LongParameterList:JokeException.kt$JokeException$( val internalError: Boolean, val code: Int, message: String, val causedBy: List<String>, val additionalInfo: String, val timestamp: Long, cause: Throwable? = null ) + LongParameterList:JokeApi.kt$( amount: Int, categories: Set<Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set<Flag> = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false ) + LongParameterList:JokeApi.kt$( categories: Set<Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set<Flag> = emptySet(), type: Type = Type.ALL, contains: String = "", idRange: IdRange = IdRange(), safe: Boolean = false, auth: String = "", splitNewLine: Boolean = false ) + LongParameterList:JokeApi.kt$( categories: Set<Category> = setOf(Category.ANY), lang: Language = Language.EN, blacklistFlags: Set<Flag> = emptySet(), type: Type = Type.ALL, format: Format = Format.JSON, contains: String = "", idRange: IdRange = IdRange(), amount: Int = 1, safe: Boolean = false, auth: String = "" ) + LongParameterList:JokeConfig.kt$JokeConfig$( val categories: Set<Category>, val language: Language, val flags: Set<Flag>, val type: Type, val format: Format, val contains: String, val idRange: IdRange, val amount: Int, val safe: Boolean, val splitNewLine: Boolean, val auth: String ) + LongParameterList:JokeConfig.kt$JokeConfig$( var categories: Set<Category> = setOf(Category.ANY), var lang: Language = Language.EN, var blacklistFlags: Set<Flag> = emptySet(), var type: Type = Type.ALL, var format: Format = Format.JSON, var contains: String = "", var idRange: IdRange = IdRange(), var amount: Int = 1, var safe: Boolean = false, var splitNewLine: Boolean = false, var auth: String = "" ) + LongParameterList:JokeException.kt$JokeException$( val internalError: Boolean, val code: Int, message: String, val causedBy: List<String>, val additionalInfo: String, val timestamp: Long, cause: Throwable? = null ) MagicNumber:JokeUtil.kt$200 MagicNumber:JokeUtil.kt$399 MagicNumber:JokeUtil.kt$400 diff --git a/pom.xml b/pom.xml index cfa8eb9..1fd22ca 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ org.jetbrains.kotlin kotlin-stdlib - 1.9.24 + 2.0.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 a4dbda1..f1bc14a 100644 --- a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeApi.kt +++ b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeApi.kt @@ -101,8 +101,8 @@ object JokeApi { fun getRawJokes(config: JokeConfig): String { return rawJokes( categories = config.categories, - lang = config.language, - blacklistFlags = config.flags, + lang = config.lang, + blacklistFlags = config.blacklistFlags, type = config.type, format = config.format, contains = config.contains, @@ -124,8 +124,8 @@ object JokeApi { fun joke(config: JokeConfig = JokeConfig.Builder().build()): Joke { return joke( categories = config.categories, - lang = config.language, - blacklistFlags = config.flags, + lang = config.lang, + blacklistFlags = config.blacklistFlags, type = config.type, contains = config.contains, idRange = config.idRange, @@ -145,8 +145,8 @@ object JokeApi { fun jokes(config: JokeConfig): Array { return jokes( categories = config.categories, - lang = config.language, - blacklistFlags = config.flags, + lang = config.lang, + blacklistFlags = config.blacklistFlags, type = config.type, contains = config.contains, idRange = config.idRange, @@ -164,6 +164,32 @@ object JokeApi { * * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. * + * @param categories JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is + * about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] category, dark + * humor will be in the [Category.DARK] category and so on. If you want jokes from all categories, you can instead use + * [Category.ANY], which will make JokeAPI randomly choose a category. + * @param lang There are two types of languages; system languages and joke languages. Both are separate from each other. + * All system messages like errors can have a certain system language, while jokes can only have a joke language. + * It is possible, that system languages don't yet exist for your language while jokes already do. + * If no suitable system language is found, JokeAPI will default to English. + * @param blacklistFlags Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be + * set on each joke, and they tell you something about the offensiveness of each joke. + * @param type Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type + * [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are separated + * because you might want to present the users the delivery after a timeout or in a different section of the UI. + * A joke of type [Type.SINGLE] only has a single string, which is the entire joke. + * @param contains If the search string filter is used, only jokes that contain the specified string will be returned. + * @param idRange If this filter is used, you will only get jokes that are within the provided range of IDs. + * You don't necessarily need to provide an ID range though, a single ID will work just fine as well. + * For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range of 5 will + * mean you will only get the 6th joke. + * @param safe Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for + * everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, its + * references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally marked as + * unsafe. + * @param auth JokeAPI has a way of whitelisting certain clients. This is achieved through an API token. + * At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a business + * and need more than 120 requests per minute. * @param splitNewLine Split newline within [Type.SINGLE] joke. */ fun joke( @@ -201,7 +227,35 @@ fun joke( * * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. * - * @param amount The required amount of jokes to return. + * @param amount This filter allows you to set a certain amount of jokes to receive in a single call. Setting the + * filter to an invalid number will result in the API defaulting to serving a single joke. Setting it to a number + * larger than 10 will make JokeAPI default to the maximum (10). + * @param categories JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is + * about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] category, dark + * humor will be in the [Category.DARK] category and so on. If you want jokes from all categories, you can instead use + * [Category.ANY], which will make JokeAPI randomly choose a category. + * @param lang There are two types of languages; system languages and joke languages. Both are separate from each other. + * All system messages like errors can have a certain system language, while jokes can only have a joke language. + * It is possible, that system languages don't yet exist for your language while jokes already do. + * If no suitable system language is found, JokeAPI will default to English. + * @param blacklistFlags Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be + * set on each joke, and they tell you something about the offensiveness of each joke. + * @param type Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type + * [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are separated + * because you might want to present the users the delivery after a timeout or in a different section of the UI. + * A joke of type [Type.SINGLE] only has a single string, which is the entire joke. + * @param contains If the search string filter is used, only jokes that contain the specified string will be returned. + * @param idRange If this filter is used, you will only get jokes that are within the provided range of IDs. + * You don't necessarily need to provide an ID range though, a single ID will work just fine as well. + * For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range of 5 will + * mean you will only get the 6th joke. + * @param safe Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for + * everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, its + * references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally marked as + * unsafe. + * @param auth JokeAPI has a way of whitelisting certain clients. This is achieved through an API token. + * At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a business + * and need more than 120 requests per minute. * @param splitNewLine Split newline within [Type.SINGLE] joke. */ fun jokes( @@ -244,7 +298,40 @@ fun jokes( /** * Returns one or more jokes. * - * Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. + * See the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details. + * + * @param categories JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is + * about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] category, dark + * humor will be in the [Category.DARK] category and so on. If you want jokes from all categories, you can instead use + * [Category.ANY], which will make JokeAPI randomly choose a category. + * @param lang There are two types of languages; system languages and joke languages. Both are separate from each other. + * All system messages like errors can have a certain system language, while jokes can only have a joke language. + * It is possible, that system languages don't yet exist for your language while jokes already do. + * If no suitable system language is found, JokeAPI will default to English. + * @param blacklistFlags Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be + * set on each joke, and they tell you something about the offensiveness of each joke. + * @param type Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type + * [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are separated + * because you might want to present the users the delivery after a timeout or in a different section of the UI. + * A joke of type [Type.SINGLE] only has a single string, which is the entire joke. + * @param contains If the search string filter is used, only jokes that contain the specified string will be returned. + * @param format Response Formats (or just "Formats") are a way to get your data in a different file format. + * Maybe your environment or language doesn't support JSON natively. In that case, JokeAPI is able to convert the + * JSON-formatted joke to a different format for you. + * @param idRange If this filter is used, you will only get jokes that are within the provided range of IDs. + * You don't necessarily need to provide an ID range though, a single ID will work just fine as well. + * For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range of 5 will + * mean you will only get the 6th joke. + * @param amount This filter allows you to set a certain amount of jokes to receive in a single call. Setting the + * filter to an invalid number will result in the API defaulting to serving a single joke. Setting it to a number + * larger than 10 will make JokeAPI default to the maximum (10). + * @param safe Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for + * everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, its + * references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally marked as + * unsafe. + * @param auth JokeAPI has a way of whitelisting certain clients. This is achieved through an API token. + * At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a business + * and need more than 120 requests per minute. */ fun rawJokes( categories: Set = setOf(Category.ANY), diff --git a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeConfig.kt b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeConfig.kt index 4537d13..d1e1cfa 100644 --- a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeConfig.kt +++ b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeConfig.kt @@ -39,19 +39,33 @@ import net.thauvin.erik.jokeapi.models.* * * Use the [Builder] to create a new configuration. */ -class JokeConfig private constructor( - val categories: Set, - val language: Language, - val flags: Set, - val type: Type, - val format: Format, - val contains: String, - val idRange: IdRange, - val amount: Int, - val safe: Boolean, - val splitNewLine: Boolean, - val auth: String +class JokeConfig( + var categories: Set = setOf(Category.ANY), + var lang: Language = Language.EN, + var blacklistFlags: Set = emptySet(), + var type: Type = Type.ALL, + var format: Format = Format.JSON, + var contains: String = "", + var idRange: IdRange = IdRange(), + var amount: Int = 1, + var safe: Boolean = false, + var splitNewLine: Boolean = false, + var auth: String = "" ) { + constructor(builder: Builder) : this() { + categories = builder.categories + lang = builder.lang + blacklistFlags = builder.blacklistFlags + type = builder.type + format = builder.format + contains = "${builder.safe}:${builder.splitNewLine}" + idRange = builder.idRange + amount = builder.amount + safe = builder.safe + splitNewLine = builder.splitNewLine + auth = builder.auth + } + /** * [Builds][build] a new configuration. * @@ -72,20 +86,86 @@ class JokeConfig private constructor( var splitNewLine: Boolean = false, var auth: String = "" ) { - fun categories(categories: Set) = apply { this.categories = categories } - fun lang(language: Language) = apply { lang = language } - fun blacklistFlags(flags: Set) = apply { blacklistFlags = flags } - fun type(type: Type) = apply { this.type = type } - fun format(format: Format) = apply { this.format = format } - fun contains(search: String) = apply { contains = search } - fun idRange(idRange: IdRange) = apply { this.idRange = idRange } - fun amount(amount: Int) = apply { this.amount = amount } - fun safe(safe: Boolean) = apply { this.safe = safe } - fun splitNewLine(splitNewLine: Boolean) = apply { this.splitNewLine = splitNewLine } - fun auth(auth: String) = apply { this.auth = auth } + /** + * JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is + * about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING] + * category, dark humor will be in the [Category.DARK] category and so on. If you want jokes from all + * categories, you can instead use [Category.ANY], which will make JokeAPI randomly choose a category. + */ + fun categories(categories: Set): Builder = apply { this.categories = categories } - fun build() = JokeConfig( - categories, lang, blacklistFlags, type, format, contains, idRange, amount, safe, splitNewLine, auth - ) + /** + * There are two types of languages; system languages and joke languages. Both are separate from each other. + * All system messages like errors can have a certain system language, while jokes can only have a joke + * language. It is possible, that system languages don't yet exist for your language while jokes already do. + * If no suitable system language is found, JokeAPI will default to English. + */ + fun lang(language: Language): Builder = apply { lang = language } + + /** + * Blacklist Flags (or just "Flags") are a more fine layer of filtering. Multiple flags can be + * set on each joke, and they tell you something about the offensiveness of each joke. + */ + fun blacklistFlags(flags: Set): Builder = apply { blacklistFlags = flags } + + /** + * Each joke comes with one of two types: [Type.SINGLE] or [Type.TWOPART]. If a joke is of type + * [Type.TWOPART], it has a setup string and a delivery string, which are both part of the joke. They are + * separated because you might want to present the users the delivery after a timeout or in a different section + * of the UI. A joke of type [Type.SINGLE] only has a single string, which is the entire joke. + */ + fun type(type: Type): Builder = apply { this.type = type } + + /** + * Response Formats (or just "Formats") are a way to get your data in a different file format. + * Maybe your environment or language doesn't support JSON natively. In that case, JokeAPI is able to convert + * the JSON-formatted joke to a different format for you. + */ + fun format(format: Format): Builder = apply { this.format = format } + + /** + * If the search string filter is used, only jokes that contain the specified string will be returned. + */ + fun contains(search: String): Builder = apply { contains = search } + + /** + * If this filter is used, you will only get jokes that are within the provided range of IDs. + * You don't necessarily need to provide an ID range though, a single ID will work just fine as well. + * For example, an ID range of 0-9 will mean you will only get one of the first 10 jokes, while an ID range + * of 5 will mean you will only get the 6th joke. + */ + fun idRange(idRange: IdRange): Builder = apply { this.idRange = idRange } + + /** + * This filter allows you to set a certain amount of jokes to receive in a single call. Setting the + * filter to an invalid number will result in the API defaulting to serving a single joke. Setting it to a + * number larger than 10 will make JokeAPI default to the maximum (10). + */ + fun amount(amount: Int): Builder = apply { this.amount = amount } + + /** + * Safe Mode. If enabled, JokeAPI will try its best to serve only jokes that are considered safe for + * everyone. Unsafe jokes are those who can be considered explicit in any way, either through the used language, + * its references or its [flags][blacklistFlags]. Jokes from the category [Category.DARK] are also generally + * marked as unsafe. + */ + fun safe(safe: Boolean): Builder = apply { this.safe = safe } + + /** + * Split newline within [Type.SINGLE] joke. + */ + fun splitNewLine(splitNewLine: Boolean): Builder = apply { this.splitNewLine = splitNewLine } + + /** + * JokeAPI has a way of whitelisting certain clients. This is achieved through an API token. + * At the moment, you will only receive one of these tokens temporarily if something breaks or if you are a + * business and need more than 120 requests per minute. + */ + fun auth(auth: String): Builder = apply { this.auth = auth } + + /** + * Builds a new comment configuration. + */ + fun build() = JokeConfig(this) } } diff --git a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt index 21006d5..be2d1d2 100644 --- a/src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt +++ b/src/main/kotlin/net/thauvin/erik/jokeapi/JokeUtil.kt @@ -42,6 +42,9 @@ import java.net.HttpURLConnection import java.net.URL import java.util.logging.Level +/** + * Fetch a URL. + */ internal fun fetchUrl(url: String, auth: String = ""): String { if (JokeApi.logger.isLoggable(Level.FINE)) { JokeApi.logger.fine(url) diff --git a/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt b/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt index e617dfc..8349c4c 100644 --- a/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt +++ b/src/test/kotlin/net/thauvin/erik/jokeapi/JokeConfigTest.kt @@ -154,8 +154,8 @@ internal class JokeConfigTest { }.build() assertThat(config, "config").all { prop(JokeConfig::categories).isEqualTo(categories) - prop(JokeConfig::language).isEqualTo(language) - prop(JokeConfig::flags).isEqualTo(flags) + prop(JokeConfig::lang).isEqualTo(language) + prop(JokeConfig::blacklistFlags).isEqualTo(flags) prop(JokeConfig::type).isEqualTo(type) prop(JokeConfig::format).isEqualTo(format) prop(JokeConfig::contains).isEqualTo(search)