Compare commits
52 commits
Author | SHA1 | Date | |
---|---|---|---|
ad99c4c838 | |||
04e636feb4 | |||
af753c7ac3 | |||
708550ad5c | |||
a2ab48e67c | |||
7df1c20e82 | |||
f737077b1d | |||
40568463dd | |||
b2163c7ee7 | |||
7ba1b0ecf6 | |||
d39542478f | |||
e211159757 | |||
f16d54fd53 | |||
4b4f778490 | |||
8978b56750 | |||
4cc92e956f | |||
b17a4fd588 | |||
944fbf1228 | |||
427dc1a248 | |||
256903cec1 | |||
41e0d866e2 | |||
3afbfb26ed | |||
ccfe3ac4db | |||
b0631046b9 | |||
97e0479ffb | |||
f0ccff6529 | |||
b95e1541fb | |||
5ac8f910b5 | |||
37517a2845 | |||
76f78a8688 | |||
137201c3e7 | |||
6bd1aed18f | |||
08780a5c73 | |||
f653a0be64 | |||
da0af8552e | |||
3d684d86c6 | |||
a7db176830 | |||
e6bfcdad80 | |||
8332db1a80 | |||
e925f7a1c2 | |||
e81c6a0492 | |||
e8deffa5ef | |||
ab15abe11f | |||
e3c7146d06 | |||
185836c91a | |||
7fecaa8f82 | |||
ca04776f8b | |||
cb0c2efd4f | |||
cdeb91c7d4 | |||
1a3c7fbac2 | |||
89b51307b3 | |||
2b4a7e5534 |
42 changed files with 730 additions and 283 deletions
|
@ -1,4 +1,8 @@
|
||||||
version: 2
|
version: 2.1
|
||||||
|
|
||||||
|
orbs:
|
||||||
|
sdkman: joshdholtz/sdkman@0.2.0
|
||||||
|
|
||||||
defaults: &defaults
|
defaults: &defaults
|
||||||
working_directory: ~/repo
|
working_directory: ~/repo
|
||||||
environment:
|
environment:
|
||||||
|
@ -6,18 +10,31 @@ defaults: &defaults
|
||||||
TERM: dumb
|
TERM: dumb
|
||||||
CI_NAME: "CircleCI"
|
CI_NAME: "CircleCI"
|
||||||
|
|
||||||
defaults_gradle: &defaults_bld
|
commands:
|
||||||
steps:
|
build_and_test:
|
||||||
- checkout
|
parameters:
|
||||||
- run:
|
reports-dir:
|
||||||
name: Download the bld dependencies
|
type: string
|
||||||
command: ./bld download
|
default: "build/reports/test_results"
|
||||||
- run:
|
steps:
|
||||||
name: Compile source with bld
|
- checkout
|
||||||
command: ./bld compile
|
- sdkman/setup-sdkman
|
||||||
- run:
|
- sdkman/sdkman-install:
|
||||||
name: Run tests with bld
|
candidate: kotlin
|
||||||
command: ./bld test
|
version: 2.0.20
|
||||||
|
- run:
|
||||||
|
name: Download dependencies
|
||||||
|
command: ./bld download
|
||||||
|
- run:
|
||||||
|
name: Compile source
|
||||||
|
command: ./bld compile
|
||||||
|
- run:
|
||||||
|
name: Run tests
|
||||||
|
command: ./bld jacoco -reports-dir=<< parameters.reports-dir >>
|
||||||
|
- store_test_results:
|
||||||
|
path: << parameters.reports-dir >>
|
||||||
|
- store_artifacts:
|
||||||
|
path: build/reports/jacoco/test/html
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
bld_jdk17:
|
bld_jdk17:
|
||||||
|
@ -26,7 +43,8 @@ jobs:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/openjdk:17.0
|
- image: cimg/openjdk:17.0
|
||||||
|
|
||||||
<<: *defaults_bld
|
steps:
|
||||||
|
- build_and_test
|
||||||
|
|
||||||
bld_jdk20:
|
bld_jdk20:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
|
@ -34,10 +52,10 @@ jobs:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/openjdk:20.0
|
- image: cimg/openjdk:20.0
|
||||||
|
|
||||||
<<: *defaults_bld
|
steps:
|
||||||
|
- build_and_test
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
|
||||||
bld:
|
bld:
|
||||||
jobs:
|
jobs:
|
||||||
- bld_jdk17
|
- bld_jdk17
|
||||||
|
|
38
.github/workflows/bld.yml
vendored
38
.github/workflows/bld.yml
vendored
|
@ -2,48 +2,50 @@ name: bld-ci
|
||||||
|
|
||||||
on: [ push, pull_request, workflow_dispatch ]
|
on: [ push, pull_request, workflow_dispatch ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
COVERAGE_JDK: "21"
|
||||||
|
COVERAGE_KOTLIN: "2.1.20"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-bld-project:
|
build-bld-project:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
env:
|
|
||||||
COVERAGE_SDK: "17"
|
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
java-version: [ 17, 20 ]
|
java-version: [ 17, 21, 24 ]
|
||||||
|
kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ]
|
||||||
|
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source repository
|
- name: Checkout source repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up JDK ${{ matrix.java-version }}
|
- name: Set up JDK ${{ matrix.java-version }} with Kotlin ${{ matrix.kotlin-version }}
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'zulu'
|
distribution: "zulu"
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
|
|
||||||
- name: Grant bld execute permission
|
- name: Download dependencies
|
||||||
run: chmod +x bld
|
|
||||||
|
|
||||||
- name: Download the bld dependencies
|
|
||||||
run: ./bld download
|
run: ./bld download
|
||||||
|
|
||||||
- name: Compile source with bld
|
- name: Compile source
|
||||||
run: ./bld compile
|
run: ./bld compile
|
||||||
|
|
||||||
- name: Run tests with bld
|
- name: Run tests
|
||||||
run: ./bld jacoco
|
run: ./bld jacoco
|
||||||
|
|
||||||
- name: Remove pom.xml
|
- name: Remove pom.xml
|
||||||
if: success() && matrix.java-version == env.COVERAGE_SDK
|
if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN
|
||||||
|
&& matrix.os == 'ubuntu-latest'
|
||||||
run: rm -rf pom.xml
|
run: rm -rf pom.xml
|
||||||
|
|
||||||
- name: SonarCloud Scan
|
- name: SonarCloud Scan
|
||||||
uses: sonarsource/sonarcloud-github-action@master
|
uses: sonarsource/sonarcloud-github-action@master
|
||||||
if: success() && matrix.java-version == env.COVERAGE_SDK
|
if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.kotlin-version == env.COVERAGE_KOTLIN
|
||||||
|
&& matrix.os == 'ubuntu-latest'
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
|
6
.idea/bld.xml
generated
Normal file
6
.idea/bld.xml
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="BldConfiguration">
|
||||||
|
<events />
|
||||||
|
</component>
|
||||||
|
</project>
|
204
.idea/intellij-javadocs-4.0.1.xml
generated
Normal file
204
.idea/intellij-javadocs-4.0.1.xml
generated
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaDocConfiguration">
|
||||||
|
<GENERAL>
|
||||||
|
<MODE>UPDATE</MODE>
|
||||||
|
<OVERRIDDEN_METHODS>false</OVERRIDDEN_METHODS>
|
||||||
|
<SPLITTED_CLASS_NAME>true</SPLITTED_CLASS_NAME>
|
||||||
|
<LEVELS>
|
||||||
|
<LEVEL>TYPE</LEVEL>
|
||||||
|
<LEVEL>METHOD</LEVEL>
|
||||||
|
<LEVEL>FIELD</LEVEL>
|
||||||
|
</LEVELS>
|
||||||
|
<VISIBILITIES>
|
||||||
|
<VISIBILITY>DEFAULT</VISIBILITY>
|
||||||
|
<VISIBILITY>PROTECTED</VISIBILITY>
|
||||||
|
<VISIBILITY>PUBLIC</VISIBILITY>
|
||||||
|
</VISIBILITIES>
|
||||||
|
</GENERAL>
|
||||||
|
<TEMPLATES>
|
||||||
|
<CLASSES>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>^.*(public|protected|private)*.+interface\s+\w+.*</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The interface ${name}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>^.*(public|protected|private)*.+enum\s+\w+.*</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The enum ${name}.\n
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>^.*(public|protected|private)*.+class\s+\w+.*</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The type ${name}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
<CLASS>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The type ${name}.\n
|
||||||
|
*/</VALUE>
|
||||||
|
</CLASS>
|
||||||
|
</CLASSES>
|
||||||
|
<CONSTRUCTORS>
|
||||||
|
<CONSTRUCTOR>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* Instantiates a new ${name}.\n
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</CONSTRUCTOR>
|
||||||
|
</CONSTRUCTORS>
|
||||||
|
<METHODS>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>^.*(public|protected|private)*\s*.*(\w(\s*<.+>)*)+\s+get\w+\s*\(.*\).+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* Gets ${partName}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if isNotVoid>
|
||||||
|
*\n
|
||||||
|
* @return the ${partName}\n
|
||||||
|
</#if>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>^.*(public|protected|private)*\s*.*(void|\w(\s*<.+>)*)+\s+set\w+\s*\(.*\).+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* Sets ${partName}.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if isNotVoid>
|
||||||
|
*\n
|
||||||
|
* @return the ${partName}\n
|
||||||
|
</#if>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The entry point of application.\n
|
||||||
|
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
* @param ${element.parameterList.parameters[0].name} the input arguments\n
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
<METHOD>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* ${name}<#if isNotVoid> ${return}</#if>.\n
|
||||||
|
<#if element.typeParameters?has_content> * \n
|
||||||
|
</#if>
|
||||||
|
<#list element.typeParameters as typeParameter>
|
||||||
|
* @param <${typeParameter.name}> the type parameter\n
|
||||||
|
</#list>
|
||||||
|
<#if element.parameterList.parameters?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.parameterList.parameters as parameter>
|
||||||
|
* @param ${parameter.name} the ${paramNames[parameter.name]}\n
|
||||||
|
</#list>
|
||||||
|
<#if isNotVoid>
|
||||||
|
*\n
|
||||||
|
* @return the ${return}\n
|
||||||
|
</#if>
|
||||||
|
<#if element.throwsList.referenceElements?has_content>
|
||||||
|
*\n
|
||||||
|
</#if>
|
||||||
|
<#list element.throwsList.referenceElements as exception>
|
||||||
|
* @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
|
||||||
|
</#list>
|
||||||
|
*/</VALUE>
|
||||||
|
</METHOD>
|
||||||
|
</METHODS>
|
||||||
|
<FIELDS>
|
||||||
|
<FIELD>
|
||||||
|
<KEY>^.*(public|protected|private)*.+static.*(\w\s\w)+.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
* The constant ${element.getName()}.\n
|
||||||
|
*/</VALUE>
|
||||||
|
</FIELD>
|
||||||
|
<FIELD>
|
||||||
|
<KEY>^.*(public|protected|private)*.*(\w\s\w)+.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
<#if element.parent.isInterface()>
|
||||||
|
* The constant ${element.getName()}.\n
|
||||||
|
<#else>
|
||||||
|
* The ${name}.\n
|
||||||
|
</#if> */</VALUE>
|
||||||
|
</FIELD>
|
||||||
|
<FIELD>
|
||||||
|
<KEY>.+</KEY>
|
||||||
|
<VALUE>/**\n
|
||||||
|
<#if element.parent.isEnum()>
|
||||||
|
*${name} ${typeName}.\n
|
||||||
|
<#else>
|
||||||
|
* The ${name}.\n
|
||||||
|
</#if>*/</VALUE>
|
||||||
|
</FIELD>
|
||||||
|
</FIELDS>
|
||||||
|
</TEMPLATES>
|
||||||
|
</component>
|
||||||
|
</project>
|
4
.idea/kotlinc.xml
generated
4
.idea/kotlinc.xml
generated
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="KotlinJpsPluginSettings">
|
<component name="KotlinJpsPluginSettings">
|
||||||
<option name="version" value="1.9.10" />
|
<option name="version" value="2.1.0" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
4
.idea/libraries/bld.xml
generated
4
.idea/libraries/bld.xml
generated
|
@ -2,12 +2,12 @@
|
||||||
<library name="bld">
|
<library name="bld">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/bld" />
|
<root url="file://$PROJECT_DIR$/lib/bld" />
|
||||||
<root url="jar://$USER_HOME$/.bld/dist/bld-1.7.5.jar!/" />
|
<root url="jar://$USER_HOME$/.bld/dist/bld-2.2.1.jar!/" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
<JAVADOC />
|
<JAVADOC />
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/bld" />
|
<root url="file://$PROJECT_DIR$/lib/bld" />
|
||||||
<root url="jar://$USER_HOME$/.bld/dist/bld-1.7.5-sources.jar!/" />
|
<root url="jar://$USER_HOME$/.bld/dist/bld-2.2.1-sources.jar!/" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<excluded>
|
<excluded>
|
||||||
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/bld/bld-wrapper.jar!/" />
|
||||||
|
|
4
.idea/libraries/compile.xml
generated
4
.idea/libraries/compile.xml
generated
|
@ -7,7 +7,7 @@
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/compile" />
|
<root url="file://$PROJECT_DIR$/lib/compile" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="true" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/compile" recursive="true" type="SOURCES" />
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
4
.idea/libraries/runtime.xml
generated
4
.idea/libraries/runtime.xml
generated
|
@ -8,7 +8,7 @@
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/runtime" />
|
<root url="file://$PROJECT_DIR$/lib/runtime" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="true" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/runtime" recursive="true" type="SOURCES" />
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
4
.idea/libraries/test.xml
generated
4
.idea/libraries/test.xml
generated
|
@ -8,7 +8,7 @@
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/lib/test" />
|
<root url="file://$PROJECT_DIR$/lib/test" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="true" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/test" recursive="true" type="SOURCES" />
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
26
.idea/misc.xml
generated
26
.idea/misc.xml
generated
|
@ -1,21 +1,19 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
|
<entry_points version="2.0">
|
||||||
|
<entry_point TYPE="field" FQNAME="net.thauvin.erik.jokeapi.models.Category SPOOKY" />
|
||||||
|
<entry_point TYPE="field" FQNAME="net.thauvin.erik.jokeapi.JokeApi logger$delegate" />
|
||||||
|
</entry_points>
|
||||||
<pattern value="net.thauvin.erik.JokeApiBuild" method="jacoco" />
|
<pattern value="net.thauvin.erik.JokeApiBuild" method="jacoco" />
|
||||||
</component>
|
<pattern value="net.thauvin.erik.JokeApiBuild" method="detekt" />
|
||||||
<component name="PDMPlugin">
|
<pattern value="net.thauvin.erik.JokeApiBuild" method="detektBaseline" />
|
||||||
<option name="customRuleSets">
|
<pattern value="net.thauvin.erik.jokeapi.models.Category" />
|
||||||
<list>
|
<pattern value="net.thauvin.erik.jokeapi.models.Category" method="Category" />
|
||||||
<option value="K:\java\semver\config\pmd.xml" />
|
<pattern value="net.thauvin.erik.jokeapi.models.Flag" method="Flag" />
|
||||||
<option value="$PROJECT_DIR$/../../java/bld-generated-version/config/pmd.xml" />
|
<pattern value="net.thauvin.erik.jokeapi.models.Format" method="Format" />
|
||||||
<option value="$PROJECT_DIR$/../../java/bld-pitest/config/pmd.xml" />
|
<pattern value="net.thauvin.erik.jokeapi.models.Language" method="Language" />
|
||||||
<option value="$PROJECT_DIR$/../../java/bld-jacoco-report/config/pmd.xml" />
|
<pattern value="net.thauvin.erik.jokeapi.models.Type" method="Type" />
|
||||||
<option value="$PROJECT_DIR$/../../java/bld-checkstyle/config/pmd.xml" />
|
|
||||||
<option value="$PROJECT_DIR$/../../java/bld-exec/config/pmd.xml" />
|
|
||||||
<option value="$PROJECT_DIR$/../../java/bld-testng/config/pmd.xml" />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
<option name="skipTestSources" value="false" />
|
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build" />
|
<output url="file://$PROJECT_DIR$/build" />
|
||||||
|
|
9
.idea/runConfigurations/Run Tests.xml
generated
9
.idea/runConfigurations/Run Tests.xml
generated
|
@ -1,9 +0,0 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="Run Tests" type="Application" factoryName="Application" nameIsGenerated="true">
|
|
||||||
<option name="MAIN_CLASS_NAME" value="net.thauvin.erik.JokeapiTest" />
|
|
||||||
<module name="app" />
|
|
||||||
<method v="2">
|
|
||||||
<option name="Make" enabled="true" />
|
|
||||||
</method>
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
11
.vscode/launch.json
vendored
11
.vscode/launch.json
vendored
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "java",
|
|
||||||
"name": "Run Tests",
|
|
||||||
"request": "launch",
|
|
||||||
"mainClass": "net.thauvin.erik.JokeapiTest"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"java.project.sourcePaths": [
|
|
||||||
"src/main/java",
|
|
||||||
"src/main/resources",
|
|
||||||
"src/test/java",
|
|
||||||
"src/bld/java"
|
|
||||||
],
|
|
||||||
"java.configuration.updateBuildConfiguration": "automatic",
|
|
||||||
"java.project.referencedLibraries": [
|
|
||||||
"${HOME}/.bld/dist/bld-1.7.5.jar",
|
|
||||||
"lib/compile/*.jar",
|
|
||||||
"lib/runtime/*.jar",
|
|
||||||
"lib/test/*.jar"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
44
README.md
44
README.md
|
@ -1,5 +1,6 @@
|
||||||
[](https://opensource.org/licenses/BSD-3-Clause)
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
||||||
[](https://kotlinlang.org/)
|
[](https://kotlinlang.org/)
|
||||||
|
[](https://rife2.com/bld)
|
||||||
[](https://github.com/ethauvin/jokeapi/releases/latest)
|
[](https://github.com/ethauvin/jokeapi/releases/latest)
|
||||||
[](https://central.sonatype.com/artifact/net.thauvin.erik/jokeapi)
|
[](https://central.sonatype.com/artifact/net.thauvin.erik/jokeapi)
|
||||||
[](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/jokeapi/)
|
[](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/jokeapi/)
|
||||||
|
@ -15,7 +16,7 @@ A simple library to retrieve jokes from [Sv443's JokeAPI](https://v2.jokeapi.dev
|
||||||
## Examples (TL;DR)
|
## Examples (TL;DR)
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import net.thauvin.erik.jokeapi.getJoke
|
import net.thauvin.erik.jokeapi.joke
|
||||||
|
|
||||||
val joke = joke()
|
val joke = joke()
|
||||||
val safe = joke(safe = true)
|
val safe = joke(safe = true)
|
||||||
|
@ -94,10 +95,10 @@ joke.getJoke().forEach(System.out::println);
|
||||||
To use with [bld](https://rife2.com/bld), include the following dependency in your build file:
|
To use with [bld](https://rife2.com/bld), include the following dependency in your build file:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
repositories = List.of(MAVEN_CENTRAL);
|
repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS_LEGACY);
|
||||||
|
|
||||||
scope(compile)
|
scope(compile)
|
||||||
.include(dependency("net.thauvin.erik:cryptoprice:1.0.1"));
|
.include(dependency("net.thauvin.erik", "jokeapi", "1.0.0"));
|
||||||
```
|
```
|
||||||
Be sure to use the [bld Kotlin extension](https://github.com/rife2/bld-kotlin) in your project.
|
Be sure to use the [bld Kotlin extension](https://github.com/rife2/bld-kotlin) in your project.
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("net.thauvin.erik:jokeapi:0.9.0")
|
implementation("net.thauvin.erik:jokeapi:1.0.0")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -123,9 +124,10 @@ You can also retrieve one or more raw (unprocessed) jokes in all [supported form
|
||||||
|
|
||||||
For example for YAML:
|
For example for YAML:
|
||||||
```kotlin
|
```kotlin
|
||||||
var joke = getRawJokes(format = Format.YAML, idRange = IdRange(22))
|
var jokes = getRawJokes(format = Format.YAML, idRange = IdRange(22))
|
||||||
println(joke)
|
println(jokes.data)
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
error: false
|
error: false
|
||||||
category: "Programming"
|
category: "Programming"
|
||||||
|
@ -141,8 +143,8 @@ flags:
|
||||||
id: 22
|
id: 22
|
||||||
safe: true
|
safe: true
|
||||||
lang: "en"
|
lang: "en"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- View more [examples](https://github.com/ethauvin/jokeapi/blob/master/src/test/kotlin/net/thauvin/erik/jokeapi/GetRawJokesTest.kt#L46)...
|
- View more [examples](https://github.com/ethauvin/jokeapi/blob/master/src/test/kotlin/net/thauvin/erik/jokeapi/GetRawJokesTest.kt#L46)...
|
||||||
|
|
||||||
## Extending
|
## Extending
|
||||||
|
@ -152,15 +154,37 @@ A generic `apiCall()` function is available to access other [JokeAPI endpoints](
|
||||||
For example to retrieve the French [language code](https://v2.jokeapi.dev/#langcode-endpoint):
|
For example to retrieve the French [language code](https://v2.jokeapi.dev/#langcode-endpoint):
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val lang = JokeApi.apiCall(
|
val response = JokeApi.apiCall(
|
||||||
endPoint = "langcode",
|
endPoint = "langcode",
|
||||||
path = "french",
|
path = "french",
|
||||||
params = mapOf(Parameter.FORMAT to Format.YAML.value)
|
params = mapOf(Parameter.FORMAT to Format.YAML.value)
|
||||||
)
|
)
|
||||||
println(lang)
|
if (response.statusCode == 200) {
|
||||||
|
println(response.data)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
error: false
|
error: false
|
||||||
code: "fr"
|
code: "fr"
|
||||||
```
|
```
|
||||||
- View more [examples](https://github.com/ethauvin/jokeapi/blob/master/src/test/kotlin/net/thauvin/erik/jokeapi/ApiCallTest.kt#L48)...
|
- View more [examples](https://github.com/ethauvin/jokeapi/blob/master/src/test/kotlin/net/thauvin/erik/jokeapi/ApiCallTest.kt#L48)...
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you want to contribute to this project, all you have to do is clone the GitHub
|
||||||
|
repository:
|
||||||
|
|
||||||
|
```console
|
||||||
|
git clone git@github.com:ethauvin/jokeapi.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use [bld](https://rife2.com/bld) to build:
|
||||||
|
|
||||||
|
```console
|
||||||
|
cd jokeapi
|
||||||
|
./bld compile
|
||||||
|
```
|
||||||
|
|
||||||
|
The project has an [IntelliJ IDEA](https://www.jetbrains.com/idea/) project structure. You can just open it after all
|
||||||
|
the dependencies were downloaded and peruse the code.
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version="1.0" ?>
|
||||||
<SmellBaseline>
|
<SmellBaseline>
|
||||||
<ManuallySuppressedIssues/>
|
<ManuallySuppressedIssues></ManuallySuppressedIssues>
|
||||||
<CurrentIssues>
|
<CurrentIssues>
|
||||||
<ID>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 )</ID>
|
<ID>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 )</ID>
|
||||||
<ID>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 )</ID>
|
<ID>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 )</ID>
|
||||||
<ID>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 = "" )</ID>
|
<ID>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 = "" )</ID>
|
||||||
<ID>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 )</ID>
|
<ID>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 )</ID>
|
||||||
<ID>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 )</ID>
|
<ID>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 )</ID>
|
||||||
<ID>MagicNumber:JokeUtil.kt$200</ID>
|
<ID>MagicNumber:JokeUtil.kt$200</ID>
|
||||||
<ID>MagicNumber:JokeUtil.kt$399</ID>
|
<ID>MagicNumber:JokeUtil.kt$399</ID>
|
||||||
<ID>MagicNumber:JokeUtil.kt$400</ID>
|
<ID>MagicNumber:JokeUtil.kt$400</ID>
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
<ID>WildcardImport:GetJokeTest.kt$import assertk.assertions.*</ID>
|
<ID>WildcardImport:GetJokeTest.kt$import assertk.assertions.*</ID>
|
||||||
<ID>WildcardImport:GetJokeTest.kt$import net.thauvin.erik.jokeapi.models.*</ID>
|
<ID>WildcardImport:GetJokeTest.kt$import net.thauvin.erik.jokeapi.models.*</ID>
|
||||||
<ID>WildcardImport:GetJokesTest.kt$import assertk.assertions.*</ID>
|
<ID>WildcardImport:GetJokesTest.kt$import assertk.assertions.*</ID>
|
||||||
|
<ID>WildcardImport:GetRawJokesTest.kt$import assertk.assertions.*</ID>
|
||||||
<ID>WildcardImport:JokeApi.kt$import net.thauvin.erik.jokeapi.models.*</ID>
|
<ID>WildcardImport:JokeApi.kt$import net.thauvin.erik.jokeapi.models.*</ID>
|
||||||
<ID>WildcardImport:JokeConfig.kt$import net.thauvin.erik.jokeapi.models.*</ID>
|
<ID>WildcardImport:JokeConfig.kt$import net.thauvin.erik.jokeapi.models.*</ID>
|
||||||
<ID>WildcardImport:JokeConfigTest.kt$import assertk.assertions.*</ID>
|
<ID>WildcardImport:JokeConfigTest.kt$import assertk.assertions.*</ID>
|
||||||
|
|
Binary file not shown.
|
@ -1,9 +1,10 @@
|
||||||
bld.downloadExtensionJavadoc=false
|
bld.downloadExtensionJavadoc=false
|
||||||
bld.downloadExtensionSources=true
|
bld.downloadExtensionSources=true
|
||||||
bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.1
|
|
||||||
bld.extensions=com.uwyn.rife2:bld-kotlin:0.9.0-SNAPSHOT
|
|
||||||
bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.0-SNAPSHOT
|
|
||||||
bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
|
|
||||||
bld.downloadLocation=
|
bld.downloadLocation=
|
||||||
|
bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.10-SNAPSHOT
|
||||||
|
bld.extension-dokka=com.uwyn.rife2:bld-dokka:1.0.4-SNAPSHOT
|
||||||
|
bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.10-SNAPSHOT
|
||||||
|
bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT
|
||||||
|
bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
|
||||||
bld.sourceDirectories=
|
bld.sourceDirectories=
|
||||||
bld.version=1.7.5
|
bld.version=2.2.1
|
||||||
|
|
26
pom.xml
26
pom.xml
|
@ -4,7 +4,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>net.thauvin.erik</groupId>
|
<groupId>net.thauvin.erik</groupId>
|
||||||
<artifactId>jokeapi</artifactId>
|
<artifactId>jokeapi</artifactId>
|
||||||
<version>0.9.1</version>
|
<version>1.0.1-SNAPSHOT</version>
|
||||||
<name>jokeapi</name>
|
<name>jokeapi</name>
|
||||||
<description>Retrieve jokes from Sv443's JokeAPI</description>
|
<description>Retrieve jokes from Sv443's JokeAPI</description>
|
||||||
<url>https://github.com/ethauvin/jokeapi</url>
|
<url>https://github.com/ethauvin/jokeapi</url>
|
||||||
|
@ -18,37 +18,19 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
<artifactId>kotlin-stdlib</artifactId>
|
<artifactId>kotlin-stdlib</artifactId>
|
||||||
<version>1.9.21</version>
|
<version>2.1.20</version>
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-common</artifactId>
|
|
||||||
<version>1.9.21</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk7</artifactId>
|
|
||||||
<version>1.9.21</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
<version>1.9.21</version>
|
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>org.json</groupId>
|
||||||
<artifactId>json</artifactId>
|
<artifactId>json</artifactId>
|
||||||
<version>20231013</version>
|
<version>20250107</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.thauvin.erik.urlencoder</groupId>
|
<groupId>net.thauvin.erik.urlencoder</groupId>
|
||||||
<artifactId>urlencoder-lib-jvm</artifactId>
|
<artifactId>urlencoder-lib-jvm</artifactId>
|
||||||
<version>1.4.0</version>
|
<version>1.6.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeApiBuild.java
|
* JokeApiBuild.java
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -35,10 +35,11 @@ import rife.bld.BuildCommand;
|
||||||
import rife.bld.Project;
|
import rife.bld.Project;
|
||||||
import rife.bld.extension.CompileKotlinOperation;
|
import rife.bld.extension.CompileKotlinOperation;
|
||||||
import rife.bld.extension.DetektOperation;
|
import rife.bld.extension.DetektOperation;
|
||||||
|
import rife.bld.extension.DokkaOperation;
|
||||||
import rife.bld.extension.JacocoReportOperation;
|
import rife.bld.extension.JacocoReportOperation;
|
||||||
import rife.bld.extension.dokka.DokkaOperation;
|
|
||||||
import rife.bld.extension.dokka.LoggingLevel;
|
import rife.bld.extension.dokka.LoggingLevel;
|
||||||
import rife.bld.extension.dokka.OutputFormat;
|
import rife.bld.extension.dokka.OutputFormat;
|
||||||
|
import rife.bld.extension.kotlin.CompileOptions;
|
||||||
import rife.bld.operations.exceptions.ExitStatusException;
|
import rife.bld.operations.exceptions.ExitStatusException;
|
||||||
import rife.bld.publish.PomBuilder;
|
import rife.bld.publish.PomBuilder;
|
||||||
import rife.bld.publish.PublishDeveloper;
|
import rife.bld.publish.PublishDeveloper;
|
||||||
|
@ -49,41 +50,45 @@ import rife.tools.exceptions.FileUtilsErrorException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.ConsoleHandler;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static rife.bld.dependencies.Repository.*;
|
import static rife.bld.dependencies.Repository.*;
|
||||||
import static rife.bld.dependencies.Scope.compile;
|
import static rife.bld.dependencies.Scope.compile;
|
||||||
import static rife.bld.dependencies.Scope.test;
|
import static rife.bld.dependencies.Scope.test;
|
||||||
|
|
||||||
public class JokeApiBuild extends Project {
|
public class JokeApiBuild extends Project {
|
||||||
|
final File srcMainKotlin = new File(srcMainDirectory(), "kotlin");
|
||||||
|
|
||||||
public JokeApiBuild() {
|
public JokeApiBuild() {
|
||||||
pkg = "net.thauvin.erik";
|
pkg = "net.thauvin.erik";
|
||||||
name = "jokeapi";
|
name = "jokeapi";
|
||||||
version = version(0, 9, 1);
|
version = version(1, 0, 1, "SNAPSHOT");
|
||||||
|
|
||||||
javaRelease = 11;
|
javaRelease = 11;
|
||||||
downloadSources = true;
|
downloadSources = true;
|
||||||
autoDownloadPurge = true;
|
autoDownloadPurge = true;
|
||||||
repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL);
|
repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL);
|
||||||
|
|
||||||
final var kotlin = version(1, 9, 21);
|
final var kotlin = version(2, 1, 20);
|
||||||
scope(compile)
|
scope(compile)
|
||||||
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin))
|
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin))
|
||||||
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-common", kotlin))
|
.include(dependency("org.json", "json", "20250107"))
|
||||||
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-jdk7", kotlin))
|
.include(dependency("net.thauvin.erik.urlencoder", "urlencoder-lib-jvm", version(1, 6, 0)));
|
||||||
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-jdk8", kotlin))
|
|
||||||
.include(dependency("org.json", "json", "20231013"))
|
|
||||||
.include(dependency("net.thauvin.erik.urlencoder", "urlencoder-lib-jvm", version(1, 4, 0)));
|
|
||||||
scope(test)
|
scope(test)
|
||||||
.include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", version(1, 9, 21)))
|
.include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin))
|
||||||
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 1)))
|
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1)))
|
||||||
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 1)))
|
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1)))
|
||||||
.include(dependency("com.willowtreeapps.assertk", "assertk-jvm", version(0, 27, 0)));
|
.include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 1)))
|
||||||
|
.include(dependency("com.willowtreeapps.assertk", "assertk-jvm", version(0, 28, 1)));
|
||||||
|
|
||||||
publishOperation()
|
publishOperation()
|
||||||
.repository(version.isSnapshot() ? repository(SONATYPE_SNAPSHOTS_LEGACY.location())
|
.repository(version.isSnapshot() ? repository(SONATYPE_SNAPSHOTS_LEGACY.location())
|
||||||
.withCredentials(property("sonatype.user"), property("sonatype.password"))
|
.withCredentials(property("sonatype.user"), property("sonatype.password"))
|
||||||
: repository(SONATYPE_RELEASES_LEGACY.location())
|
: repository(SONATYPE_RELEASES_LEGACY.location())
|
||||||
.withCredentials(property("sonatype.user"), property("sonatype.password")))
|
.withCredentials(property("sonatype.user"), property("sonatype.password")))
|
||||||
|
.repository(repository("github"))
|
||||||
.info()
|
.info()
|
||||||
.groupId(pkg)
|
.groupId(pkg)
|
||||||
.artifactId(name)
|
.artifactId(name)
|
||||||
|
@ -110,18 +115,29 @@ public class JokeApiBuild extends Project {
|
||||||
.signKey(property("sign.key"))
|
.signKey(property("sign.key"))
|
||||||
.signPassphrase(property("sign.passphrase"));
|
.signPassphrase(property("sign.passphrase"));
|
||||||
|
|
||||||
jarSourcesOperation().sourceDirectories(new File(srcMainDirectory(), "kotlin"));
|
jarSourcesOperation().sourceDirectories(srcMainKotlin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
// Enable detailed logging for the extensions
|
||||||
|
var level = Level.ALL;
|
||||||
|
var logger = Logger.getLogger("rife.bld.extension");
|
||||||
|
var consoleHandler = new ConsoleHandler();
|
||||||
|
|
||||||
|
consoleHandler.setLevel(level);
|
||||||
|
logger.addHandler(consoleHandler);
|
||||||
|
logger.setLevel(level);
|
||||||
|
logger.setUseParentHandlers(false);
|
||||||
|
|
||||||
new JokeApiBuild().start(args);
|
new JokeApiBuild().start(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BuildCommand(summary = "Compiles the Kotlin project")
|
@BuildCommand(summary = "Compiles the Kotlin project")
|
||||||
@Override
|
@Override
|
||||||
public void compile() throws IOException {
|
public void compile() throws Exception {
|
||||||
new CompileKotlinOperation()
|
new CompileKotlinOperation()
|
||||||
.fromProject(this)
|
.fromProject(this)
|
||||||
|
.compileOptions(new CompileOptions().verbose(true))
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,9 +158,10 @@ public class JokeApiBuild extends Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
@BuildCommand(summary = "Generates JaCoCo Reports")
|
@BuildCommand(summary = "Generates JaCoCo Reports")
|
||||||
public void jacoco() throws IOException {
|
public void jacoco() throws Exception {
|
||||||
new JacocoReportOperation()
|
new JacocoReportOperation()
|
||||||
.fromProject(this)
|
.fromProject(this)
|
||||||
|
.sourceFiles(srcMainKotlin)
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +183,12 @@ public class JokeApiBuild extends Project {
|
||||||
pomRoot();
|
pomRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publishLocal() throws Exception {
|
||||||
|
super.publishLocal();
|
||||||
|
pomRoot();
|
||||||
|
}
|
||||||
|
|
||||||
@BuildCommand(value = "pom-root", summary = "Generates the POM file in the root directory")
|
@BuildCommand(value = "pom-root", summary = "Generates the POM file in the root directory")
|
||||||
public void pomRoot() throws FileUtilsErrorException {
|
public void pomRoot() throws FileUtilsErrorException {
|
||||||
PomBuilder.generateInto(publishOperation().fromProject(this).info(), dependencies(),
|
PomBuilder.generateInto(publishOperation().fromProject(this).info(), dependencies(),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeApi.kt
|
* JokeApi.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -45,13 +45,16 @@ import java.util.stream.Collectors
|
||||||
object JokeApi {
|
object JokeApi {
|
||||||
private const val API_URL = "https://v2.jokeapi.dev/"
|
private const val API_URL = "https://v2.jokeapi.dev/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger instance.
|
||||||
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val logger: Logger by lazy { Logger.getLogger(JokeApi::class.java.simpleName) }
|
val logger: Logger by lazy { Logger.getLogger(JokeApi::class.java.simpleName) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a direct API call.
|
* Makes a direct API call.
|
||||||
*
|
*
|
||||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#endpoints) for more details.
|
* See the [JokeAPI Documentation](https://jokeapi.dev/#endpoints) for more details.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
|
@ -61,7 +64,7 @@ object JokeApi {
|
||||||
path: String = "",
|
path: String = "",
|
||||||
params: Map<String, String> = emptyMap(),
|
params: Map<String, String> = emptyMap(),
|
||||||
auth: String = ""
|
auth: String = ""
|
||||||
): String {
|
): JokeResponse {
|
||||||
val urlBuilder = StringBuilder("$API_URL$endPoint")
|
val urlBuilder = StringBuilder("$API_URL$endPoint")
|
||||||
|
|
||||||
if (path.isNotEmpty()) {
|
if (path.isNotEmpty()) {
|
||||||
|
@ -95,11 +98,11 @@ object JokeApi {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(HttpErrorException::class)
|
@Throws(HttpErrorException::class)
|
||||||
fun getRawJokes(config: JokeConfig): String {
|
fun getRawJokes(config: JokeConfig): JokeResponse {
|
||||||
return rawJokes(
|
return rawJokes(
|
||||||
categories = config.categories,
|
categories = config.categories,
|
||||||
lang = config.language,
|
lang = config.lang,
|
||||||
blacklistFlags = config.flags,
|
blacklistFlags = config.blacklistFlags,
|
||||||
type = config.type,
|
type = config.type,
|
||||||
format = config.format,
|
format = config.format,
|
||||||
contains = config.contains,
|
contains = config.contains,
|
||||||
|
@ -121,8 +124,8 @@ object JokeApi {
|
||||||
fun joke(config: JokeConfig = JokeConfig.Builder().build()): Joke {
|
fun joke(config: JokeConfig = JokeConfig.Builder().build()): Joke {
|
||||||
return joke(
|
return joke(
|
||||||
categories = config.categories,
|
categories = config.categories,
|
||||||
lang = config.language,
|
lang = config.lang,
|
||||||
blacklistFlags = config.flags,
|
blacklistFlags = config.blacklistFlags,
|
||||||
type = config.type,
|
type = config.type,
|
||||||
contains = config.contains,
|
contains = config.contains,
|
||||||
idRange = config.idRange,
|
idRange = config.idRange,
|
||||||
|
@ -142,8 +145,8 @@ object JokeApi {
|
||||||
fun jokes(config: JokeConfig): Array<Joke> {
|
fun jokes(config: JokeConfig): Array<Joke> {
|
||||||
return jokes(
|
return jokes(
|
||||||
categories = config.categories,
|
categories = config.categories,
|
||||||
lang = config.language,
|
lang = config.lang,
|
||||||
blacklistFlags = config.flags,
|
blacklistFlags = config.blacklistFlags,
|
||||||
type = config.type,
|
type = config.type,
|
||||||
contains = config.contains,
|
contains = config.contains,
|
||||||
idRange = config.idRange,
|
idRange = config.idRange,
|
||||||
|
@ -161,6 +164,32 @@ object JokeApi {
|
||||||
*
|
*
|
||||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
* 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.
|
* @param splitNewLine Split newline within [Type.SINGLE] joke.
|
||||||
*/
|
*/
|
||||||
fun joke(
|
fun joke(
|
||||||
|
@ -184,7 +213,7 @@ fun joke(
|
||||||
idRange = idRange,
|
idRange = idRange,
|
||||||
safe = safe,
|
safe = safe,
|
||||||
auth = auth
|
auth = auth
|
||||||
)
|
).data
|
||||||
)
|
)
|
||||||
if (json.getBoolean("error")) {
|
if (json.getBoolean("error")) {
|
||||||
throw parseError(json)
|
throw parseError(json)
|
||||||
|
@ -198,7 +227,35 @@ fun joke(
|
||||||
*
|
*
|
||||||
* Sse the [JokeAPI Documentation](https://jokeapi.dev/#joke-endpoint) for more details.
|
* 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.
|
* @param splitNewLine Split newline within [Type.SINGLE] joke.
|
||||||
*/
|
*/
|
||||||
fun jokes(
|
fun jokes(
|
||||||
|
@ -224,7 +281,7 @@ fun jokes(
|
||||||
amount = amount,
|
amount = amount,
|
||||||
safe = safe,
|
safe = safe,
|
||||||
auth = auth
|
auth = auth
|
||||||
)
|
).data
|
||||||
)
|
)
|
||||||
if (json.getBoolean("error")) {
|
if (json.getBoolean("error")) {
|
||||||
throw parseError(json)
|
throw parseError(json)
|
||||||
|
@ -241,8 +298,42 @@ fun jokes(
|
||||||
/**
|
/**
|
||||||
* Returns one or more 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.
|
||||||
*/
|
*/
|
||||||
|
@Throws(HttpErrorException::class)
|
||||||
fun rawJokes(
|
fun rawJokes(
|
||||||
categories: Set<Category> = setOf(Category.ANY),
|
categories: Set<Category> = setOf(Category.ANY),
|
||||||
lang: Language = Language.EN,
|
lang: Language = Language.EN,
|
||||||
|
@ -254,7 +345,7 @@ fun rawJokes(
|
||||||
amount: Int = 1,
|
amount: Int = 1,
|
||||||
safe: Boolean = false,
|
safe: Boolean = false,
|
||||||
auth: String = ""
|
auth: String = ""
|
||||||
): String {
|
): JokeResponse {
|
||||||
val params = mutableMapOf<String, String>()
|
val params = mutableMapOf<String, String>()
|
||||||
|
|
||||||
// Categories
|
// Categories
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeConfig.kt
|
* JokeConfig.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -39,19 +39,19 @@ import net.thauvin.erik.jokeapi.models.*
|
||||||
*
|
*
|
||||||
* Use the [Builder] to create a new configuration.
|
* Use the [Builder] to create a new configuration.
|
||||||
*/
|
*/
|
||||||
class JokeConfig private constructor(
|
class JokeConfig private constructor(builder: Builder) {
|
||||||
val categories: Set<Category>,
|
val categories = builder.categories
|
||||||
val language: Language,
|
val lang = builder.lang
|
||||||
val flags: Set<Flag>,
|
val blacklistFlags = builder.blacklistFlags
|
||||||
val type: Type,
|
val type = builder.type
|
||||||
val format: Format,
|
val format = builder.format
|
||||||
val contains: String,
|
val contains = builder.contains
|
||||||
val idRange: IdRange,
|
val idRange = builder.idRange
|
||||||
val amount: Int,
|
val amount = builder.amount
|
||||||
val safe: Boolean,
|
val safe = builder.safe
|
||||||
val splitNewLine: Boolean,
|
val splitNewLine = builder.splitNewLine
|
||||||
val auth: String
|
val auth = builder.auth
|
||||||
) {
|
|
||||||
/**
|
/**
|
||||||
* [Builds][build] a new configuration.
|
* [Builds][build] a new configuration.
|
||||||
*
|
*
|
||||||
|
@ -72,20 +72,86 @@ class JokeConfig private constructor(
|
||||||
var splitNewLine: Boolean = false,
|
var splitNewLine: Boolean = false,
|
||||||
var auth: String = ""
|
var auth: String = ""
|
||||||
) {
|
) {
|
||||||
fun categories(categories: Set<Category>) = apply { this.categories = categories }
|
/**
|
||||||
fun lang(language: Language) = apply { lang = language }
|
* JokeAPI has a first, coarse filter that just categorizes the jokes depending on what the joke is
|
||||||
fun blacklistFlags(flags: Set<Flag>) = apply { blacklistFlags = flags }
|
* about or who the joke is directed at. A joke about programming will be in the [Category.PROGRAMMING]
|
||||||
fun type(type: Type) = apply { this.type = type }
|
* category, dark humor will be in the [Category.DARK] category and so on. If you want jokes from all
|
||||||
fun format(format: Format) = apply { this.format = format }
|
* categories, you can instead use [Category.ANY], which will make JokeAPI randomly choose a category.
|
||||||
fun contains(search: String) = apply { contains = search }
|
*/
|
||||||
fun idRange(idRange: IdRange) = apply { this.idRange = idRange }
|
fun categories(categories: Set<Category>): Builder = apply { this.categories = categories }
|
||||||
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 }
|
|
||||||
|
|
||||||
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<Flag>): 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 configuration.
|
||||||
|
*/
|
||||||
|
fun build() = JokeConfig(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeUtil.kt
|
* JokeUtil.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -39,30 +39,37 @@ import net.thauvin.erik.jokeapi.models.*
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URI
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
internal fun fetchUrl(url: String, auth: String = ""): String {
|
/**
|
||||||
|
* Fetch a URL.
|
||||||
|
*/
|
||||||
|
internal fun fetchUrl(url: String, auth: String = ""): JokeResponse {
|
||||||
if (JokeApi.logger.isLoggable(Level.FINE)) {
|
if (JokeApi.logger.isLoggable(Level.FINE)) {
|
||||||
JokeApi.logger.fine(url)
|
JokeApi.logger.fine(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
val connection = URL(url).openConnection() as HttpURLConnection
|
val connection = URI(url).toURL().openConnection() as HttpURLConnection
|
||||||
connection.setRequestProperty(
|
try {
|
||||||
"User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
|
connection.setRequestProperty(
|
||||||
)
|
"User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0"
|
||||||
if (auth.isNotEmpty()) {
|
)
|
||||||
connection.setRequestProperty("Authentication", auth)
|
if (auth.isNotEmpty()) {
|
||||||
}
|
connection.setRequestProperty("Authentication", auth)
|
||||||
|
}
|
||||||
|
|
||||||
if (connection.responseCode in 200..399) {
|
val isSuccess = connection.responseCode in 200..399
|
||||||
val body = connection.inputStream.bufferedReader().use { it.readText() }
|
val stream = if (isSuccess) connection.inputStream else connection.errorStream
|
||||||
if (JokeApi.logger.isLoggable(Level.FINE)) {
|
val body = stream.bufferedReader().use { it.readText() }
|
||||||
|
if (!isSuccess && (body.isBlank() || connection.contentType.contains("text/html"))) {
|
||||||
|
throw httpError(connection.responseCode)
|
||||||
|
} else if (JokeApi.logger.isLoggable(Level.FINE)) {
|
||||||
JokeApi.logger.fine(body)
|
JokeApi.logger.fine(body)
|
||||||
}
|
}
|
||||||
return body
|
return JokeResponse(connection.responseCode, body)
|
||||||
} else {
|
} finally {
|
||||||
throw httpError(connection.responseCode)
|
connection.disconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +130,9 @@ private fun httpError(responseCode: Int): HttpErrorException {
|
||||||
return httpException
|
return httpException
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse Error.
|
||||||
|
*/
|
||||||
internal fun parseError(json: JSONObject): JokeException {
|
internal fun parseError(json: JSONObject): JokeException {
|
||||||
val causedBy = json.getJSONArray("causedBy")
|
val causedBy = json.getJSONArray("causedBy")
|
||||||
val causes = List<String>(causedBy.length()) { i -> causedBy.getString(i) }
|
val causes = List<String>(causedBy.length()) { i -> causedBy.getString(i) }
|
||||||
|
@ -136,6 +146,9 @@ internal fun parseError(json: JSONObject): JokeException {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse Joke.
|
||||||
|
*/
|
||||||
internal fun parseJoke(json: JSONObject, splitNewLine: Boolean): Joke {
|
internal fun parseJoke(json: JSONObject, splitNewLine: Boolean): Joke {
|
||||||
val jokes = mutableListOf<String>()
|
val jokes = mutableListOf<String>()
|
||||||
if (json.has("setup")) {
|
if (json.has("setup")) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* HttpErrorException.kt
|
* HttpErrorException.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -44,7 +44,6 @@ class HttpErrorException @JvmOverloads constructor(
|
||||||
cause: Throwable? = null
|
cause: Throwable? = null
|
||||||
) : IOException(message, cause) {
|
) : IOException(message, cause) {
|
||||||
companion object {
|
companion object {
|
||||||
@Suppress("ConstPropertyName")
|
|
||||||
private const val serialVersionUID = 1L
|
private const val serialVersionUID = 1L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeException.kt
|
* JokeException.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Category.kt
|
* Category.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Flag.kt
|
* Flag.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Format.kt
|
* Format.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* IdRange.kt
|
* IdRange.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Joke.kt
|
* Joke.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* JokeResponse.kt
|
||||||
|
*
|
||||||
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of this project nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package net.thauvin.erik.jokeapi.models
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Joke API response.
|
||||||
|
*
|
||||||
|
* @property statusCode The HTTP status code.
|
||||||
|
* @property data The response body text.
|
||||||
|
*/
|
||||||
|
data class JokeResponse(val statusCode: Int, val data: String)
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Language.kt
|
* Language.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Parameter.kt
|
* Parameter.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -34,6 +34,7 @@ package net.thauvin.erik.jokeapi.models
|
||||||
/**
|
/**
|
||||||
* The available [URL Parameters](https://jokeapi.dev/#url-parameters).
|
* The available [URL Parameters](https://jokeapi.dev/#url-parameters).
|
||||||
*/
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
object Parameter {
|
object Parameter {
|
||||||
const val AMOUNT = "amount"
|
const val AMOUNT = "amount"
|
||||||
const val CONTAINS = "contains"
|
const val CONTAINS = "contains"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Type.kt
|
* Type.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* ApiCallTest.kt
|
* ApiCallTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
package net.thauvin.erik.jokeapi
|
package net.thauvin.erik.jokeapi
|
||||||
|
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
|
import assertk.assertions.isEqualTo
|
||||||
import assertk.assertions.isGreaterThan
|
import assertk.assertions.isGreaterThan
|
||||||
import assertk.assertions.startsWith
|
import assertk.assertions.startsWith
|
||||||
import net.thauvin.erik.jokeapi.JokeApi.apiCall
|
import net.thauvin.erik.jokeapi.JokeApi.apiCall
|
||||||
|
@ -51,8 +52,9 @@ internal class ApiCallTest {
|
||||||
fun `Get Flags`() {
|
fun `Get Flags`() {
|
||||||
// See https://v2.jokeapi.dev/#flags-endpoint
|
// See https://v2.jokeapi.dev/#flags-endpoint
|
||||||
val response = apiCall(endPoint = "flags")
|
val response = apiCall(endPoint = "flags")
|
||||||
val json = JSONObject(response)
|
val json = JSONObject(response.data)
|
||||||
assertAll("Validate JSON",
|
assertAll(
|
||||||
|
"Validate JSON",
|
||||||
{ assertFalse(json.getBoolean("error"), "apiCall(flags).error") },
|
{ assertFalse(json.getBoolean("error"), "apiCall(flags).error") },
|
||||||
{ assertThat(json.getJSONArray("flags").length(), "apiCall(flags).flags").isGreaterThan(0) },
|
{ assertThat(json.getJSONArray("flags").length(), "apiCall(flags).flags").isGreaterThan(0) },
|
||||||
{ assertThat(json.getLong("timestamp"), "apiCall(flags).timestamp").isGreaterThan(0) })
|
{ assertThat(json.getLong("timestamp"), "apiCall(flags).timestamp").isGreaterThan(0) })
|
||||||
|
@ -65,14 +67,16 @@ internal class ApiCallTest {
|
||||||
endPoint = "langcode", path = "french",
|
endPoint = "langcode", path = "french",
|
||||||
params = mapOf(Parameter.FORMAT to Format.YAML.value)
|
params = mapOf(Parameter.FORMAT to Format.YAML.value)
|
||||||
)
|
)
|
||||||
assertContains(lang, "code: \"fr\"", false, "apiCall(langcode, french, yaml)")
|
assertThat(lang.statusCode).isEqualTo(200)
|
||||||
|
assertContains(lang.data, "code: \"fr\"", false, "apiCall(langcode, french, yaml)")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Ping Response`() {
|
fun `Get Ping Response`() {
|
||||||
// See https://v2.jokeapi.dev/#ping-endpoint
|
// See https://v2.jokeapi.dev/#ping-endpoint
|
||||||
val ping = apiCall(endPoint = "ping", params = mapOf(Parameter.FORMAT to Format.TXT.value))
|
val ping = apiCall(endPoint = "ping", params = mapOf(Parameter.FORMAT to Format.TXT.value))
|
||||||
assertThat(ping, "apiCall(ping, txt)").startsWith("Pong!")
|
assertThat(ping.statusCode).isEqualTo(200)
|
||||||
|
assertThat(ping.data).startsWith("Pong!")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -82,6 +86,7 @@ internal class ApiCallTest {
|
||||||
endPoint = "languages",
|
endPoint = "languages",
|
||||||
params = mapOf(Parameter.FORMAT to Format.XML.value, Parameter.LANG to Language.FR.value)
|
params = mapOf(Parameter.FORMAT to Format.XML.value, Parameter.LANG to Language.FR.value)
|
||||||
)
|
)
|
||||||
assertThat(lang).startsWith("<?xml version='1.0'?>")
|
assertThat(lang.statusCode).isEqualTo(200)
|
||||||
|
assertThat(lang.data).startsWith("<?xml version='1.0'?>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* BeforeAllTests.kt
|
* BeforeAllTests.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* ExceptionsTest.kt
|
* ExceptionsTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -41,8 +41,6 @@ import net.thauvin.erik.jokeapi.models.Category
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
import org.junit.jupiter.params.ParameterizedTest
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource
|
|
||||||
|
|
||||||
@ExtendWith(BeforeAllTests::class)
|
@ExtendWith(BeforeAllTests::class)
|
||||||
internal class ExceptionsTest {
|
internal class ExceptionsTest {
|
||||||
|
@ -63,19 +61,20 @@ internal class ExceptionsTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(ints = [400, 404, 403, 413, 414, 429, 500, 523, 666])
|
fun `Validate HTTP Exceptions`() {
|
||||||
fun `Validate HTTP Exceptions`(code: Int) {
|
val locs = ArrayList<Pair<String, Int>>()
|
||||||
val e = assertThrows<HttpErrorException> {
|
locs.add(Pair("https://apichallenges.herokuapp.com/secret/note", 401))
|
||||||
fetchUrl("https://httpstat.us/$code")
|
locs.add(Pair("https://apichallenges.herokuapp.com/todo", 404))
|
||||||
}
|
|
||||||
assertThat(e, "fetchUrl($code)").all {
|
for ((url, code) in locs) {
|
||||||
prop(HttpErrorException::statusCode).isEqualTo(code)
|
val e = assertThrows<HttpErrorException> {
|
||||||
prop(HttpErrorException::message).isNotNull().isNotEmpty()
|
fetchUrl(url)
|
||||||
if (code < 600)
|
}
|
||||||
prop(HttpErrorException::cause).isNotNull().assertThat(Throwable::message).isNotNull()
|
assertThat(e, "fetchUrl($code)").all {
|
||||||
else
|
prop(HttpErrorException::statusCode).isEqualTo(code)
|
||||||
prop(HttpErrorException::cause).isNull()
|
prop(HttpErrorException::message).isNotNull().isNotEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* GetJokeTest.kt
|
* GetJokeTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -70,15 +70,12 @@ internal class GetJokeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Joke with ID`() {
|
fun `Get Joke with ID`() {
|
||||||
val id = 172
|
val id = 201
|
||||||
val joke = joke(idRange = IdRange(id))
|
val joke = joke(idRange = IdRange(id))
|
||||||
logger.fine(joke.toString())
|
logger.fine(joke.toString())
|
||||||
assertThat(joke, "joke($id)").all {
|
assertThat(joke, "joke($id)").all {
|
||||||
prop(Joke::flags).all {
|
prop(Joke::flags).contains(Flag.RELIGIOUS);
|
||||||
contains(Flag.EXPLICIT)
|
prop(Joke::id).isEqualTo(id)
|
||||||
contains(Flag.NSFW)
|
|
||||||
}
|
|
||||||
prop(Joke::id).isEqualTo(172)
|
|
||||||
prop(Joke::category).isEqualTo(Category.PUN)
|
prop(Joke::category).isEqualTo(Category.PUN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,12 +134,10 @@ internal class GetJokeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Joke with Split Newline`() {
|
fun `Get Joke with Split Newline`() {
|
||||||
val joke = joke(
|
val joke = joke(type = Type.SINGLE, idRange = IdRange(18), splitNewLine = true)
|
||||||
categories = setOf(Category.DARK), type = Type.SINGLE, idRange = IdRange(178), splitNewLine = true
|
|
||||||
)
|
|
||||||
logger.fine(joke.toString())
|
logger.fine(joke.toString())
|
||||||
assertThat(joke::joke, "joke(splitNewLine=true)").all {
|
assertThat(joke::joke, "joke(splitNewLine=true)").all {
|
||||||
size().isEqualTo(2)
|
size().isGreaterThanOrEqualTo(2)
|
||||||
each {
|
each {
|
||||||
containsNone("\n")
|
containsNone("\n")
|
||||||
}
|
}
|
||||||
|
@ -177,13 +172,12 @@ internal class GetJokeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Joke using Search`() {
|
fun `Get Joke using Search`() {
|
||||||
val id = 265
|
val search = "UDP joke"
|
||||||
val search = "his wife"
|
|
||||||
val joke =
|
val joke =
|
||||||
joke(contains = search, categories = setOf(Category.PROGRAMMING), idRange = IdRange(id), safe = true)
|
joke(contains = search, categories = setOf(Category.PROGRAMMING), safe = true)
|
||||||
logger.fine(joke.toString())
|
logger.fine(joke.toString())
|
||||||
assertThat(joke, "joke($search)").all {
|
assertThat(joke, "joke($search)").all {
|
||||||
prop(Joke::id).isEqualTo(id)
|
prop(Joke::id).isEqualTo(0)
|
||||||
prop(Joke::joke).any {
|
prop(Joke::joke).any {
|
||||||
it.contains(search)
|
it.contains(search)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* GetJokesTest.kt
|
* GetJokesTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* GetRawJokesTest.kt
|
* GetRawJokesTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -33,47 +33,60 @@ package net.thauvin.erik.jokeapi
|
||||||
|
|
||||||
import assertk.all
|
import assertk.all
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.doesNotContain
|
import assertk.assertions.*
|
||||||
import assertk.assertions.isNotEmpty
|
|
||||||
import assertk.assertions.startsWith
|
|
||||||
import net.thauvin.erik.jokeapi.models.Format
|
import net.thauvin.erik.jokeapi.models.Format
|
||||||
import net.thauvin.erik.jokeapi.models.IdRange
|
import net.thauvin.erik.jokeapi.models.IdRange
|
||||||
|
import net.thauvin.erik.jokeapi.models.JokeResponse
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
import kotlin.test.assertContains
|
|
||||||
|
|
||||||
@ExtendWith(BeforeAllTests::class)
|
@ExtendWith(BeforeAllTests::class)
|
||||||
internal class GetRawJokesTest {
|
internal class GetRawJokesTest {
|
||||||
@Test
|
@Test
|
||||||
fun `Get Raw Joke with TXT`() {
|
fun `Get Raw Joke with TXT`() {
|
||||||
val response = rawJokes(format = Format.TXT)
|
val response = rawJokes(format = Format.TXT)
|
||||||
assertThat(response, "rawJoke(txt)").all {
|
assertThat(response).all {
|
||||||
isNotEmpty()
|
prop("statusCode", JokeResponse::statusCode).isEqualTo(200)
|
||||||
doesNotContain("Error")
|
prop("data", JokeResponse::data).all {
|
||||||
|
isNotEmpty()
|
||||||
|
doesNotContain("Error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Raw Joke with XML`() {
|
fun `Get Raw Joke with XML`() {
|
||||||
val response = rawJokes(format = Format.XML)
|
val response = rawJokes(format = Format.XML)
|
||||||
assertThat(response, "rawJoke(xml)").startsWith("<?xml version='1.0'?>\n<data>\n <error>false</error>")
|
assertThat(response).all {
|
||||||
|
prop("statusCode", JokeResponse::statusCode).isEqualTo(200)
|
||||||
|
prop("data", JokeResponse::data).startsWith("<?xml version='1.0'?>\n<data>\n <error>false</error>")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Raw Joke with YAML`() {
|
fun `Get Raw Joke with YAML`() {
|
||||||
val response = rawJokes(format = Format.YAML)
|
val response = rawJokes(format = Format.YAML)
|
||||||
assertThat(response, "rawJoke(yaml)").startsWith("error: false")
|
assertThat(response).all {
|
||||||
|
prop("statusCode", JokeResponse::statusCode).isEqualTo(200)
|
||||||
|
prop("data", JokeResponse::data).startsWith("error: false")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Raw Jokes`() {
|
fun `Get Raw Jokes`() {
|
||||||
val response = rawJokes(amount = 2)
|
val response = rawJokes(amount = 2)
|
||||||
assertContains(response, "\"amount\": 2", false, "rawJoke(2)")
|
assertThat(response).all {
|
||||||
|
prop("statusCode", JokeResponse::statusCode).isEqualTo(200)
|
||||||
|
prop("data", JokeResponse::data).isNotEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Get Raw Invalid Jokes`() {
|
fun `Get Raw Invalid Jokes`() {
|
||||||
val response = rawJokes(contains = "foo", safe = true, amount = 2, idRange = IdRange(160, 161))
|
val response = rawJokes(contains = "foo", safe = true, amount = 2, idRange = IdRange(160, 161))
|
||||||
assertContains(response, "\"error\": true", false, "getRawJokes(foo)")
|
assertThat(response).all {
|
||||||
|
prop("statusCode", JokeResponse::statusCode).isEqualTo(400)
|
||||||
|
prop("data", JokeResponse::data).contains("\"error\": true")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeConfigTest.kt
|
* JokeConfigTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -102,8 +102,9 @@ internal class JokeConfigTest {
|
||||||
amount(2)
|
amount(2)
|
||||||
safe(true)
|
safe(true)
|
||||||
}.build()
|
}.build()
|
||||||
val joke = getRawJokes(config)
|
val jokes = getRawJokes(config)
|
||||||
assertContains(joke, "----------------------------------------------", false, "config.amount(2)")
|
assertThat(jokes.statusCode).isEqualTo(200)
|
||||||
|
assertContains(jokes.data, "----------------------------------------------", false, "config.amount(2)")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -154,8 +155,8 @@ internal class JokeConfigTest {
|
||||||
}.build()
|
}.build()
|
||||||
assertThat(config, "config").all {
|
assertThat(config, "config").all {
|
||||||
prop(JokeConfig::categories).isEqualTo(categories)
|
prop(JokeConfig::categories).isEqualTo(categories)
|
||||||
prop(JokeConfig::language).isEqualTo(language)
|
prop(JokeConfig::lang).isEqualTo(language)
|
||||||
prop(JokeConfig::flags).isEqualTo(flags)
|
prop(JokeConfig::blacklistFlags).isEqualTo(flags)
|
||||||
prop(JokeConfig::type).isEqualTo(type)
|
prop(JokeConfig::type).isEqualTo(type)
|
||||||
prop(JokeConfig::format).isEqualTo(format)
|
prop(JokeConfig::format).isEqualTo(format)
|
||||||
prop(JokeConfig::contains).isEqualTo(search)
|
prop(JokeConfig::contains).isEqualTo(search)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* JokeUtilTest.kt
|
* JokeUtilTest.kt
|
||||||
*
|
*
|
||||||
* Copyright 2022-2023 Erik C. Thauvin (erik@thauvin.net)
|
* Copyright 2022-2025 Erik C. Thauvin (erik@thauvin.net)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -33,6 +33,7 @@ package net.thauvin.erik.jokeapi
|
||||||
|
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.contains
|
import assertk.assertions.contains
|
||||||
|
import assertk.assertions.isEqualTo
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
@ -54,7 +55,8 @@ internal class JokeUtilTest {
|
||||||
@Test
|
@Test
|
||||||
fun `Validate Authentication Header`() {
|
fun `Validate Authentication Header`() {
|
||||||
val token = "AUTH-TOKEN"
|
val token = "AUTH-TOKEN"
|
||||||
val body = fetchUrl("https://postman-echo.com/get", token)
|
val response = fetchUrl("https://postman-echo.com/get", token)
|
||||||
assertThat(body, "body").contains("\"authentication\": \"$token\"")
|
assertThat(response.statusCode).isEqualTo(200)
|
||||||
|
assertThat(response.data, "body").contains("\"authentication\": \"$token\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue