diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a0b7843..42bc1da 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,6 +1,6 @@ name: gradle-ci -on: [push, pull_request, workflow_dispatch] +on: [ push, pull_request, workflow_dispatch ] jobs: build: @@ -8,20 +8,21 @@ jobs: env: GRADLE_OPTS: "-Dorg.gradle.jvmargs=-XX:MaxMetaspaceSize=512m" - SONAR_JDK: "11" + SONAR_JDK: "17" strategy: matrix: - java-version: [ 11, 18 ] + java-version: [ 11, 17, 20 ] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: + distribution: 'zulu' java-version: ${{ matrix.java-version }} - name: Grant execute permission for gradlew @@ -29,33 +30,20 @@ jobs: - name: Cache SonarCloud packages if: matrix.java-version == env.SONAR_JDK - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ matrix.java-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle-${{ matrix.java-version }}- - - name: Test with Gradle - run: ./gradlew build check --stacktrace + uses: gradle/gradle-build-action@v2 + with: + arguments: build check --stacktrace - name: SonarCloud if: success() && matrix.java-version == env.SONAR_JDK env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: ./gradlew sonarqube - - - name: Cleanup Gradle Cache - run: | - rm -f ~/.gradle/caches/modules-2/modules-2.lock - rm -f ~/.gradle/caches/modules-2/gc.properties + run: ./gradlew sonar --info diff --git a/.gitignore b/.gitignore index 13a066e..0742f86 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,6 @@ dist/ ehthumbs.db fabric.properties gen/ -gradle.properties hs_err_pid* kobaltBuild kobaltw*-test diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f30e74b..1a3e8b4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: gradle:7-jdk11 +image: gradle:8-jdk11 variables: GRADLE_OPTS: "-Dorg.gradle.daemon=false" diff --git a/.idea/kotlinScripting.xml b/.idea/kotlinScripting.xml deleted file mode 100644 index bc444de..0000000 --- a/.idea/kotlinScripting.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 2b8a50f..f8467b4 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index b674354..c9a5d1f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/README.md b/README.md index e3ba552..0e7a2fa 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ [![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause) -[![Kotlin](https://img.shields.io/badge/kotlin-1.8.0-blue)](https://kotlinlang.org/) +[![Kotlin](https://img.shields.io/badge/kotlin-1.9.10-7f52ff)](https://kotlinlang.org/) [![Nexus Snapshot](https://img.shields.io/nexus/s/net.thauvin.erik/isgd-shorten?label=snapshot&server=https%3A%2F%2Foss.sonatype.org%2F)](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/isgd-shorten/) [![release](https://img.shields.io/github/release/ethauvin/isgd-shorten.svg)](https://github.com/ethauvin/isgd-shorten/releases/latest) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/isgd-shorten/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/isgd-shorten) +[![Maven Central](https://img.shields.io/maven-central/v/net.thauvin.erik/isgd-shorten.svg?color=blue)](https://central.sonatype.com/artifact/net.thauvin.erik/isgd-shorten) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ethauvin_isgd-shorten&metric=alert_status)](https://sonarcloud.io/dashboard?id=ethauvin_isgd-shorten) [![GitHub CI](https://github.com/ethauvin/isgd-shorten/actions/workflows/gradle.yml/badge.svg)](https://github.com/ethauvin/isgd-shorten/actions/workflows/gradle.yml) @@ -46,7 +46,12 @@ returns: All of the [is.gd API](https://is.gd/developers.php) parameters are supported: ```kotlin -Isgd.shorten(url = url, shorturl="foobar", callback = "test", logstats = true, format = Format.JSON) +Isgd.shorten( + url = url, + shorturl="foobar", + callback = "test", + logstats = true, + format = Format.JSON) ``` returns: @@ -67,8 +72,31 @@ dependencies { implementation("net.thauvin.erik:isgd-shorten:0.9.2") } ``` -Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/isgd-shorten). +Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://central.sonatype.com/artifact/net.thauvin.erik/isgd-shorten). +## Java + +To make it easier to use the library with Java, configuration builders are available: + +```java +var config = new Config.Builder() + .url("https://www.example.com/") + .shorturl("foobar") + .callback("test") + .logstats(true) + .format(Format.JSON) + .build(); + +Isgd.shorten(config); +``` +```java +var config = new Config.Builder() + .shortUrl("https://is.gd/Pt2sET") + .format(Format.XML) + .build(); + +Isgd.lookup(config); +``` ### Errors An `IsgdException` is thrown when an API error occurs. The error message (text, XML or JSON) and HTTP status code can be retrieved as follows: diff --git a/build.gradle.kts b/build.gradle.kts index d2e302c..59fe0e8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,20 +1,20 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("com.github.ben-manes.versions") version "0.44.0" - id("io.gitlab.arturbosch.detekt") version "1.22.0" + id("com.github.ben-manes.versions") version "0.48.0" + id("io.gitlab.arturbosch.detekt") version "1.23.1" id("java") id("java-library") id("maven-publish") id("net.thauvin.erik.gradle.semver") version "1.0.4" - id("org.jetbrains.dokka") version "1.7.20" - id("org.jetbrains.kotlinx.kover") version "0.6.1" - id("org.sonarqube") version "3.5.0.2730" + id("org.jetbrains.dokka") version "1.9.0" + id("org.jetbrains.kotlinx.kover") version "0.7.3" + id("org.sonarqube") version "4.3.1.3277" id("signing") - kotlin("jvm") version "1.8.0" - kotlin("kapt") version "1.8.0" + kotlin("jvm") version "1.9.10" + kotlin("kapt") version "1.9.10" } group = "net.thauvin.erik" @@ -34,11 +34,11 @@ repositories { dependencies { implementation(platform(kotlin("bom"))) - implementation("net.thauvin.erik:urlencoder:1.3.0") + implementation("net.thauvin.erik.urlencoder:urlencoder-lib:1.4.0") testImplementation(kotlin("test")) testImplementation(kotlin("test-junit")) - testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25") + testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.27.0") } java { @@ -47,6 +47,17 @@ java { withSourcesJar() } +koverReport { + defaults { + xml { + onCheck = true + } + html { + onCheck = true + } + } +} + detekt { //toolVersion = "main-SNAPSHOT" baseline = project.rootDir.resolve("config/detekt/baseline.xml") @@ -58,7 +69,7 @@ sonarqube { property("sonar.organization", "ethauvin-github") property("sonar.host.url", "https://sonarcloud.io") property("sonar.sourceEncoding", "UTF-8") - property("sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/kover/xml/report.xml") + property("sonar.coverage.jacoco.xmlReportPaths", "${layout.buildDirectory.get()}/reports/kover/report.xml") } } @@ -96,6 +107,15 @@ tasks { } } + dokkaJavadoc { + dokkaSourceSets { + configureEach { + includes.from("config/dokka/packages.md") + } + } + mustRunAfter("kaptKotlin") + } + val copyToDeploy by registering(Copy::class) { from(configurations.runtimeClasspath) { exclude("annotations-*.jar") @@ -122,7 +142,7 @@ tasks { register("deploy") { description = "Copies all needed files to the $deployDir directory." group = PublishingPlugin.PUBLISH_TASK_GROUP - dependsOn(clean, wrapper, build, jar) + dependsOn(clean, build, jar) outputs.dir(deployDir) inputs.files(copyToDeploy) mustRunAfter(clean) @@ -131,11 +151,7 @@ tasks { register("release") { description = "Publishes version ${project.version} to local repository." group = PublishingPlugin.PUBLISH_TASK_GROUP - dependsOn(wrapper, "deploy", gitTag, publishToMavenLocal) - } - - "sonarqube" { - dependsOn(koverReport) + dependsOn("deploy", gitTag, publishToMavenLocal) } } @@ -163,8 +179,8 @@ publishing { } } scm { - connection.set("scm:git://github.com/$gitHub.git") - developerConnection.set("scm:git@github.com:$gitHub.git") + connection.set("scm:git:https://github.com/$gitHub.git") + developerConnection.set("scm:git:git@github.com:$gitHub.git") url.set(mavenUrl) } issueManagement { diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index f7b49af..693c365 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -5,5 +5,6 @@ LongParameterList:Isgd.kt$Isgd.Companion$( url: String, shorturl: String = "", callback: String = "", logstats: Boolean = false, format: Format = Format.SIMPLE, isVgd: Boolean = false ) MagicNumber:Isgd.kt$Isgd.Companion$200 MagicNumber:Isgd.kt$Isgd.Companion$399 + WildcardImport:IsgdTest.kt$import assertk.assertions.* diff --git a/config/dokka/packages.md b/config/dokka/packages.md new file mode 100644 index 0000000..69146fb --- /dev/null +++ b/config/dokka/packages.md @@ -0,0 +1,5 @@ +# Module isgd-shorten + +Isgd Shortener for Kotlin, Java & Android + +A simple implementation of the `is.gd` URL shortening and lookup APIs. diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index ef12539..33af313 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -2,8 +2,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("application") - id("com.github.ben-manes.versions") version "0.44.0" - kotlin("jvm") version "1.8.0" + id("com.github.ben-manes.versions") version "0.48.0" + kotlin("jvm") version "1.9.10" } // ./gradlew run --args='https://www.example.com https://is.gd/Pt2sET' diff --git a/examples/gradle/wrapper/gradle-wrapper.jar b/examples/gradle/wrapper/gradle-wrapper.jar index 7454180..033e24c 100644 Binary files a/examples/gradle/wrapper/gradle-wrapper.jar and b/examples/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/gradle/wrapper/gradle-wrapper.properties b/examples/gradle/wrapper/gradle-wrapper.properties index 070cb70..9f4197d 100644 --- a/examples/gradle/wrapper/gradle-wrapper.properties +++ b/examples/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/examples/gradlew b/examples/gradlew index 1b6c787..fcb6fca 100755 --- a/examples/gradlew +++ b/examples/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +130,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,6 +197,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in @@ -205,6 +213,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/examples/gradlew.bat b/examples/gradlew.bat index 107acd3..93e3f59 100644 --- a/examples/gradlew.bat +++ b/examples/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..7f93135 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 070cb70..ac72c34 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..0adc8e1 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,6 +198,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd3..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/pom.xml b/pom.xml index a3b26de..2e58948 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,8 @@ - scm:git://github.com/ethauvin/isgd-shorten.git - scm:git@github.com:ethauvin/isgd-shorten.git + scm:git:https://github.com/ethauvin/isgd-shorten.git + scm:git:git@github.com:ethauvin/isgd-shorten.git https://github.com/ethauvin/isgd-shorten @@ -40,7 +40,7 @@ org.jetbrains.kotlin kotlin-bom - 1.8.0 + 1.9.10 pom import @@ -50,13 +50,13 @@ org.jetbrains.kotlin kotlin-stdlib-jdk8 - 1.8.0 + 1.9.10 compile - net.thauvin.erik - urlencoder - 1.3.0 + net.thauvin.erik.urlencoder + urlencoder-lib-jvm + 1.4.0 runtime diff --git a/src/main/kotlin/net/thauvin/erik/isgd/Config.kt b/src/main/kotlin/net/thauvin/erik/isgd/Config.kt new file mode 100644 index 0000000..f6bcb9d --- /dev/null +++ b/src/main/kotlin/net/thauvin/erik/isgd/Config.kt @@ -0,0 +1,72 @@ +/* + * Config.kt + * + * Copyright 2023 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.isgd + +/** + * Provides a builder to create/lookup an is.gd shortlink. + */ +class Config private constructor( + val url: String, + val shorturl: String, + val callback: String, + val logstats: Boolean, + val format: Format, + val isVgd: Boolean +) { + /** + * Configures the parameters to create/lookup an is.gd shortlink. + */ + data class Builder( + var url: String = "", + var shorturl: String = "", + var callback: String = "", + var logstats: Boolean = false, + var format: Format = Format.SIMPLE, + var isVgd: Boolean = false + ) { + fun url(url: String) = apply { this.url = url } + fun shorturl(shorturl: String) = apply { this.shorturl = shorturl } + fun callback(callback: String) = apply { this.callback = callback } + fun logstats(logstats: Boolean) = apply { this.logstats = logstats } + fun format(format: Format) = apply { this.format = format } + fun isVgd(isVgd: Boolean) = apply { this.isVgd = isVgd } + + fun build() = Config( + url, + shorturl, + callback, + logstats, + format, + isVgd + ) + } +} diff --git a/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt b/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt index 27b2af7..4c6728c 100644 --- a/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt +++ b/src/main/kotlin/net/thauvin/erik/isgd/Isgd.kt @@ -31,7 +31,7 @@ package net.thauvin.erik.isgd -import net.thauvin.erik.urlencoder.UrlEncoder +import net.thauvin.erik.urlencoder.UrlEncoderUtil import java.net.HttpURLConnection import java.net.URL @@ -42,7 +42,7 @@ enum class Format(val type: String) { WEB("web"), SIMPLE("simple"), XML("xml"), JSON("json") } -fun String.encode(): String = UrlEncoder.encode(this) +fun String.encode(): String = UrlEncoderUtil.encode(this) /** * Implements the [is.gd API](https://is.gd/developers.php). @@ -69,6 +69,24 @@ class Isgd private constructor() { } /** + * Lookup a shortlink. + * + * See the [is.gd API](https://is.gd/apilookupreference.php). + */ + @JvmStatic + @Throws(IsgdException::class) + fun lookup(config: Config): String { + return lookup( + config.shorturl, + config.callback, + config.format, + config.isVgd + ) + } + + /** + * Lookup a shortlink. + * * See the [is.gd API](https://is.gd/apilookupreference.php). */ @JvmStatic @@ -94,6 +112,26 @@ class Isgd private constructor() { } /** + * Shortens a link. + * + * See the [is.gd API](https://is.gd/apishorteningreference.php). + */ + @JvmStatic + @Throws(IsgdException::class) + fun shorten(config: Config): String { + return shorten( + config.url, + config.shorturl, + config.callback, + config.logstats, + config.format, + config.isVgd + ) + } + + /** + * Shortens a link. + * * See the [is.gd API](https://is.gd/apishorteningreference.php). */ @JvmStatic diff --git a/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt b/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt index 59ca783..e01e4ee 100644 --- a/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt +++ b/src/test/kotlin/net/thauvin/erik/isgd/IsgdTest.kt @@ -33,12 +33,7 @@ package net.thauvin.erik.isgd import assertk.all import assertk.assertThat -import assertk.assertions.contains -import assertk.assertions.isEqualTo -import assertk.assertions.isNotNull -import assertk.assertions.matches -import assertk.assertions.prop -import assertk.assertions.startsWith +import assertk.assertions.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -66,6 +61,15 @@ class IsgdTest { } } + @Test + fun testExceptionConfig() { + assertFailsWith( + message = "shorten(config:duplicate)", + exceptionClass = IsgdException::class, + block = { Isgd.shorten(Config.Builder().url(shortUrl).build()) } + ) + } + @Test fun testLookup() { assertFailsWith( @@ -75,15 +79,35 @@ class IsgdTest { ) } + @Test + fun testLookupConfig() { + assertFailsWith( + message = "lookup(config:empty)", + exceptionClass = IllegalArgumentException::class, + block = { Isgd.lookup(Config.Builder().shorturl("").build()) } + ) + } + @Test fun testLookupDefault() { assertEquals(url, Isgd.lookup(shortUrl)) assertEquals(url, Isgd.lookup(shortVgdUrl, isVgd = true), "lookup(isVgd)") } + @Test + fun testLookupDefaultConfig() { + assertEquals(url, Isgd.lookup(Config.Builder().shorturl(shortUrl).build()), "lookup(config)") + assertEquals( + url, Isgd.lookup( + Config.Builder().shorturl(shortVgdUrl).isVgd(true).build() + ), "lookup(config:isVgd)" + ) + } + @Test fun testLookupJson() { assertEquals("{ \"url\": \"$url\" }", Isgd.lookup(shortUrl, format = Format.JSON)) + assertEquals( "test({ \"url\": \"$url\" });", Isgd.lookup(shortUrl, callback = "test", format = Format.JSON), @@ -91,6 +115,20 @@ class IsgdTest { ) } + @Test + fun testLookupJsonConfig() { + assertEquals( + "{ \"url\": \"$url\" }", + Isgd.lookup(Config.Builder().shorturl(shortUrl).format(Format.JSON).build()), "lookup(config)" + ) + + assertEquals( + "test({ \"url\": \"$url\" });", + Isgd.lookup(Config.Builder().shorturl(shortUrl).callback("test").format(Format.JSON).build()), + "lookup(config:callback)" + ) + } + @Test fun testLookupXml() { assertEquals( @@ -99,6 +137,15 @@ class IsgdTest { ) } + @Test + fun testLookupXmlConfig() { + assertEquals( + "$url", + Isgd.lookup(Config.Builder().shorturl(shortUrl).format(Format.XML).build()), + "lookup(config:xml)" + ) + } + @Test fun testShorten() { assertFailsWith( @@ -114,13 +161,38 @@ class IsgdTest { ) } + @Test + fun testShortenConfig() { + assertFailsWith( + message = "shorten(config:empty)", + exceptionClass = IllegalArgumentException::class, + block = { Isgd.shorten(Config.Builder().url("").build()) } + ) + + assertFailsWith( + message = "shorten(config:shorturl)", + exceptionClass = IsgdException::class, + block = { Isgd.shorten(Config.Builder(url).shorturl("test").build()) } + ) + } + @Test fun testShortenDefault() { assertEquals(shortUrl, Isgd.shorten(url), "shorten(url)") assertEquals(shortVgdUrl, Isgd.shorten(url, isVgd = true), "shorten(isVgd)") assertThat(Isgd.shorten(url, logstats = true), "shorten(callback)").matches("https://is.gd/\\w{6}".toRegex()) + } - + @Test + fun testShortenDefaultConfig() { + assertEquals(shortUrl, Isgd.shorten(Config.Builder().url(url).build()), "shorten(config:url)") + assertEquals( + shortVgdUrl, + Isgd.shorten(Config.Builder().url(url).isVgd(true).build()), + "shorten(config:isVgd)" + ) + assertThat(Isgd.shorten(Config.Builder().url(url).logstats(true).build()), "shorten(config:callback)") + .matches("https://is.gd/\\w{6}".toRegex()) } @Test @@ -133,6 +205,19 @@ class IsgdTest { ) } + @Test + fun testShortenJsonConfig() { + assertEquals( + "{ \"shorturl\": \"$shortUrl\" }", + Isgd.shorten(Config.Builder().url(url).format(Format.JSON).build()), "shorten(config:json)" + ) + assertEquals( + "test({ \"shorturl\": \"$shortUrl\" });", + Isgd.shorten(Config.Builder().url(url).callback("test").format(Format.JSON).build()), + "shorten(config:callback,json)" + ) + } + @Test fun testShortenXml() { assertEquals( @@ -142,8 +227,24 @@ class IsgdTest { ) } + @Test + fun testShortenXmlConfig() { + assertEquals( + "" + + "$shortUrl", + Isgd.shorten(Config.Builder().url(url).format(Format.XML).build()), + "shorten(config:xml)" + ) + } + @Test fun testShortenWeb() { assertThat(Isgd.shorten(url, format = Format.WEB)).contains(shortUrl) } + + @Test + fun testShortenWebConfig() { + assertThat(Isgd.shorten(Config.Builder().url(url).format(Format.WEB).build()), "shorten(config:web)") + .contains(shortUrl) + } }