Added Btilink creation config builder. Closes #10
This commit is contained in:
parent
725ea3b23b
commit
e64afca3cc
4 changed files with 161 additions and 59 deletions
|
@ -31,10 +31,12 @@
|
||||||
|
|
||||||
package net.thauvin.erik.bitly
|
package net.thauvin.erik.bitly
|
||||||
|
|
||||||
import net.thauvin.erik.bitly.Utils.Companion.isSevereLoggable
|
import net.thauvin.erik.bitly.Utils.isSevereLoggable
|
||||||
import net.thauvin.erik.bitly.Utils.Companion.isValidUrl
|
import net.thauvin.erik.bitly.Utils.isValidUrl
|
||||||
import net.thauvin.erik.bitly.Utils.Companion.removeHttp
|
import net.thauvin.erik.bitly.Utils.removeHttp
|
||||||
import net.thauvin.erik.bitly.Utils.Companion.toEndPoint
|
import net.thauvin.erik.bitly.Utils.toEndPoint
|
||||||
|
import net.thauvin.erik.bitly.config.CreateConfig
|
||||||
|
import net.thauvin.erik.bitly.config.UpdateConfig
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
@ -79,7 +81,7 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
if (bitlink.isNotBlank()) {
|
if (bitlink.isNotBlank()) {
|
||||||
lastCallResponse = Utils.call(
|
lastCallResponse = Utils.call(
|
||||||
accessToken,
|
accessToken,
|
||||||
("/bitlinks/${bitlink.removeHttp()}/clicks/summary").toEndPoint(),
|
("bitlinks/${bitlink.removeHttp()}/clicks/summary").toEndPoint(),
|
||||||
mapOf(
|
mapOf(
|
||||||
"unit" to unit.toString().lowercase(),
|
"unit" to unit.toString().lowercase(),
|
||||||
"units" to units.toString(),
|
"units" to units.toString(),
|
||||||
|
@ -93,6 +95,27 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
return clicks
|
return clicks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a long url to a Bitlink and sets additional parameters.
|
||||||
|
*
|
||||||
|
* See the [Bit.ly API](https://dev.bitly.com/api-reference#createFullBitlink) for more information.
|
||||||
|
*
|
||||||
|
* @param config The parameters' configuration.
|
||||||
|
* @return The shortened URL or an empty string on error.
|
||||||
|
*/
|
||||||
|
@Synchronized
|
||||||
|
fun create(config: CreateConfig): String {
|
||||||
|
return create(
|
||||||
|
config.domain,
|
||||||
|
config.title,
|
||||||
|
config.group_guid,
|
||||||
|
config.tags,
|
||||||
|
config.deepLinks,
|
||||||
|
config.long_url,
|
||||||
|
config.toJson
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a long url to a Bitlink and sets additional parameters.
|
* Converts a long url to a Bitlink and sets additional parameters.
|
||||||
*
|
*
|
||||||
|
@ -102,10 +125,9 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
* @param group_guid A GUID for a Bitly group.
|
* @param group_guid A GUID for a Bitly group.
|
||||||
* @param long_url The long URL.
|
* @param long_url The long URL.
|
||||||
* @param toJson Returns the full JSON response if `true`.
|
* @param toJson Returns the full JSON response if `true`.
|
||||||
* @return The shorten URL or an empty string on error.
|
* @return The shortened URL or an empty string on error.
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@JvmOverloads
|
|
||||||
fun create(
|
fun create(
|
||||||
domain: String = Constants.EMPTY,
|
domain: String = Constants.EMPTY,
|
||||||
title: String = Constants.EMPTY,
|
title: String = Constants.EMPTY,
|
||||||
|
@ -119,7 +141,7 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
if (long_url.isNotBlank()) {
|
if (long_url.isNotBlank()) {
|
||||||
lastCallResponse = Utils.call(
|
lastCallResponse = Utils.call(
|
||||||
accessToken,
|
accessToken,
|
||||||
"/bitlinks".toEndPoint(),
|
"bitlinks".toEndPoint(),
|
||||||
mutableMapOf<String, Any>("long_url" to long_url).apply {
|
mutableMapOf<String, Any>("long_url" to long_url).apply {
|
||||||
if (domain.isNotBlank()) put("domain", domain)
|
if (domain.isNotBlank()) put("domain", domain)
|
||||||
if (title.isNotBlank()) put("title", title)
|
if (title.isNotBlank()) put("title", title)
|
||||||
|
@ -149,7 +171,7 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
if (bitlink_id.isNotBlank()) {
|
if (bitlink_id.isNotBlank()) {
|
||||||
lastCallResponse = Utils.call(
|
lastCallResponse = Utils.call(
|
||||||
accessToken,
|
accessToken,
|
||||||
"/expand".toEndPoint(),
|
"expand".toEndPoint(),
|
||||||
mapOf("bitlink_id" to bitlink_id.removeHttp())
|
mapOf("bitlink_id" to bitlink_id.removeHttp())
|
||||||
)
|
)
|
||||||
longUrl = parseJsonResponse(lastCallResponse, "long_url", longUrl, toJson)
|
longUrl = parseJsonResponse(lastCallResponse, "long_url", longUrl, toJson)
|
||||||
|
@ -213,7 +235,7 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
if (domain.isNotBlank()) put("domain", domain)
|
if (domain.isNotBlank()) put("domain", domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastCallResponse = Utils.call(accessToken, "/shorten".toEndPoint(), params)
|
lastCallResponse = Utils.call(accessToken, "shorten".toEndPoint(), params)
|
||||||
|
|
||||||
bitlink = parseJsonResponse(lastCallResponse, "link", bitlink, toJson)
|
bitlink = parseJsonResponse(lastCallResponse, "link", bitlink, toJson)
|
||||||
}
|
}
|
||||||
|
@ -223,11 +245,11 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates fields in the specified Bitlink.
|
* Updates parameters in the specified Bitlink.
|
||||||
*
|
*
|
||||||
* See the [Bit.ly API](https://dev.bitly.com/api-reference#updateBitlink) for more information.
|
* See the [Bit.ly API](https://dev.bitly.com/api-reference#updateBitlink) for more information.
|
||||||
*
|
*
|
||||||
* @param config The update configuration.
|
* @param config The parameters' configuration.
|
||||||
* @return [Constants.TRUE] if the update was successful, [Constants.FALSE] otherwise.
|
* @return [Constants.TRUE] if the update was successful, [Constants.FALSE] otherwise.
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -251,7 +273,7 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates fields in the specified Bitlink.
|
* Updates parameters in the specified Bitlink.
|
||||||
*
|
*
|
||||||
* See the [Bit.ly API](https://dev.bitly.com/api-reference#updateBitlink) for more information.
|
* See the [Bit.ly API](https://dev.bitly.com/api-reference#updateBitlink) for more information.
|
||||||
*
|
*
|
||||||
|
@ -260,7 +282,6 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
* @return [Constants.TRUE] if the update was successful, [Constants.FALSE] otherwise.
|
* @return [Constants.TRUE] if the update was successful, [Constants.FALSE] otherwise.
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@JvmOverloads
|
|
||||||
fun update(
|
fun update(
|
||||||
bitlink: String,
|
bitlink: String,
|
||||||
references: Map<String, String> = emptyMap(),
|
references: Map<String, String> = emptyMap(),
|
||||||
|
@ -280,7 +301,7 @@ open class Bitlinks(private val accessToken: String) {
|
||||||
var result = if (toJson) Constants.EMPTY_JSON else Constants.FALSE
|
var result = if (toJson) Constants.EMPTY_JSON else Constants.FALSE
|
||||||
if (bitlink.isNotBlank()) {
|
if (bitlink.isNotBlank()) {
|
||||||
lastCallResponse = Utils.call(
|
lastCallResponse = Utils.call(
|
||||||
accessToken, "/bitlinks/${bitlink.removeHttp()}".toEndPoint(), mutableMapOf<String, Any>().apply {
|
accessToken, "bitlinks/${bitlink.removeHttp()}".toEndPoint(), mutableMapOf<String, Any>().apply {
|
||||||
if (references.isNotEmpty()) put("references", references)
|
if (references.isNotEmpty()) put("references", references)
|
||||||
if (archived) put("archived", true)
|
if (archived) put("archived", true)
|
||||||
if (tags.isNotEmpty()) put("tags", tags)
|
if (tags.isNotEmpty()) put("tags", tags)
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* CreateConfig.kt
|
||||||
|
*
|
||||||
|
* Copyright 2020-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.bitly.config
|
||||||
|
|
||||||
|
import net.thauvin.erik.bitly.Constants
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a builder to create a Bitlink.
|
||||||
|
*/
|
||||||
|
class CreateConfig private constructor(
|
||||||
|
val domain: String,
|
||||||
|
val title: String,
|
||||||
|
val group_guid: String,
|
||||||
|
val tags: Array<String>,
|
||||||
|
val deepLinks: Array<Map<String, String>>,
|
||||||
|
val long_url: String,
|
||||||
|
val toJson: Boolean
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Configures the creation parameters of a Bitlink.
|
||||||
|
*
|
||||||
|
* See the [Bit.ly API](https://dev.bitly.com/api-reference#createFullBitlink) for more information.
|
||||||
|
**/
|
||||||
|
@Suppress("unused", "ArrayInDataClass")
|
||||||
|
data class Builder(
|
||||||
|
var domain: String = Constants.EMPTY,
|
||||||
|
var title: String = Constants.EMPTY,
|
||||||
|
var group_guid: String = Constants.EMPTY,
|
||||||
|
var tags: Array<String> = emptyArray(),
|
||||||
|
var deeplinks: Array<Map<String, String>> = emptyArray(),
|
||||||
|
var long_url: String = Constants.EMPTY,
|
||||||
|
var toJson: Boolean = false
|
||||||
|
) {
|
||||||
|
fun domain(domain: String) = apply { this.domain = domain }
|
||||||
|
fun title(title: String) = apply { this.title = title }
|
||||||
|
fun group_guid(group_guid: String) = apply { this.group_guid = group_guid }
|
||||||
|
fun tags(tags: Array<String>) = apply { this.tags = tags }
|
||||||
|
fun deeplinks(deeplinks: Array<Map<String, String>>) = apply { this.deeplinks = deeplinks }
|
||||||
|
fun longUrl(long_url: String) = apply { this.long_url = long_url }
|
||||||
|
fun toJson(toJson: Boolean) = apply { this.toJson = toJson }
|
||||||
|
|
||||||
|
fun build() = CreateConfig(
|
||||||
|
domain,
|
||||||
|
title,
|
||||||
|
group_guid,
|
||||||
|
tags,
|
||||||
|
deeplinks,
|
||||||
|
long_url,
|
||||||
|
toJson
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,8 +29,13 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.thauvin.erik.bitly
|
package net.thauvin.erik.bitly.config
|
||||||
|
|
||||||
|
import net.thauvin.erik.bitly.Constants
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a builder to update a Bitlink.
|
||||||
|
*/
|
||||||
class UpdateConfig private constructor(
|
class UpdateConfig private constructor(
|
||||||
val bitlink: String,
|
val bitlink: String,
|
||||||
val references: Map<String, String>,
|
val references: Map<String, String>,
|
||||||
|
@ -47,7 +52,12 @@ class UpdateConfig private constructor(
|
||||||
val id: String,
|
val id: String,
|
||||||
val toJson: Boolean,
|
val toJson: Boolean,
|
||||||
) {
|
) {
|
||||||
@Suppress("unused")
|
/**
|
||||||
|
* Configures the update parameters of a Bitlink.
|
||||||
|
*
|
||||||
|
* See the [Bit.ly API](https://dev.bitly.com/api-reference#updateBitlink) for more information.
|
||||||
|
**/
|
||||||
|
@Suppress("unused", "ArrayInDataClass")
|
||||||
data class Builder(
|
data class Builder(
|
||||||
var bitlink: String = Constants.EMPTY,
|
var bitlink: String = Constants.EMPTY,
|
||||||
var references: Map<String, String> = emptyMap(),
|
var references: Map<String, String> = emptyMap(),
|
||||||
|
@ -95,47 +105,5 @@ class UpdateConfig private constructor(
|
||||||
id,
|
id,
|
||||||
toJson
|
toJson
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (javaClass != other?.javaClass) return false
|
|
||||||
|
|
||||||
other as Builder
|
|
||||||
|
|
||||||
if (bitlink != other.bitlink) return false
|
|
||||||
if (references != other.references) return false
|
|
||||||
if (archived != other.archived) return false
|
|
||||||
if (!tags.contentEquals(other.tags)) return false
|
|
||||||
if (created_at != other.created_at) return false
|
|
||||||
if (title != other.title) return false
|
|
||||||
if (!deeplinks.contentEquals(other.deeplinks)) return false
|
|
||||||
if (created_by != other.created_by) return false
|
|
||||||
if (long_url != other.long_url) return false
|
|
||||||
if (client_id != other.client_id) return false
|
|
||||||
if (!custom_bitlinks.contentEquals(other.custom_bitlinks)) return false
|
|
||||||
if (link != other.link) return false
|
|
||||||
if (id != other.id) return false
|
|
||||||
if (toJson != other.toJson) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = bitlink.hashCode()
|
|
||||||
result = 31 * result + references.hashCode()
|
|
||||||
result = 31 * result + archived.hashCode()
|
|
||||||
result = 31 * result + tags.contentHashCode()
|
|
||||||
result = 31 * result + created_at.hashCode()
|
|
||||||
result = 31 * result + title.hashCode()
|
|
||||||
result = 31 * result + deeplinks.contentHashCode()
|
|
||||||
result = 31 * result + created_by.hashCode()
|
|
||||||
result = 31 * result + long_url.hashCode()
|
|
||||||
result = 31 * result + client_id.hashCode()
|
|
||||||
result = 31 * result + custom_bitlinks.contentHashCode()
|
|
||||||
result = 31 * result + link.hashCode()
|
|
||||||
result = 31 * result + id.hashCode()
|
|
||||||
result = 31 * result + toJson.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -184,6 +184,38 @@ class BitlyTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `create bitlink with config`() {
|
||||||
|
var config = CreateConfig.Builder().apply {
|
||||||
|
long_url = longUrl
|
||||||
|
}.build()
|
||||||
|
assertThat(bitly.bitlinks().create(config), "create(config)")
|
||||||
|
.matches("https://\\w+.\\w{2}/\\w{7}".toRegex())
|
||||||
|
|
||||||
|
config = CreateConfig.Builder().apply {
|
||||||
|
domain = "bit.ly"
|
||||||
|
title = "Erik's Blog"
|
||||||
|
tags = arrayOf("erik", "thauvin", "blog", "weblog")
|
||||||
|
long_url = longUrl
|
||||||
|
}.build()
|
||||||
|
assertEquals(
|
||||||
|
shortUrl,
|
||||||
|
bitly.bitlinks().create(config)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `shorten with invalid domain`() {
|
||||||
|
val bl = bitly.bitlinks()
|
||||||
|
bl.shorten("https://www.examples.com", domain = "foo.com")
|
||||||
|
assertThat(bl.lastCallResponse).all {
|
||||||
|
prop(CallResponse::isSuccessful).isFalse()
|
||||||
|
prop(CallResponse::isBadRequest).isTrue()
|
||||||
|
prop(CallResponse::message).isEqualTo("INVALID_ARG_DOMAIN")
|
||||||
|
prop(CallResponse::description).contains("invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `update bitlink`() {
|
fun `update bitlink`() {
|
||||||
val bl = bitly.bitlinks()
|
val bl = bitly.bitlinks()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue