Update functions to match the bit.ly API. Closes #14

This commit is contained in:
Erik C. Thauvin 2024-05-18 17:01:01 -07:00
parent 9a17fbe8e7
commit 55bc8d9e6a
Signed by: erik
GPG key ID: 776702A6A2DA330E
4 changed files with 104 additions and 145 deletions

View file

@ -61,7 +61,6 @@ open class Bitlinks(private val accessToken: String) {
* @param bitlink A Bitlink made of the domain and hash. * @param bitlink A Bitlink made of the domain and hash.
* @param unit A [unit of time][Units]. * @param unit A [unit of time][Units].
* @param units An integer representing the time units to query data for. Pass -1 to return all units available. * @param units An integer representing the time units to query data for. Pass -1 to return all units available.
* @param size The quantity of items to be be returned.
* @param unit_reference An ISO-8601 timestamp, indicating the most recent time for which to pull metrics. * @param unit_reference An ISO-8601 timestamp, indicating the most recent time for which to pull metrics.
* Will default to current time. * Will default to current time.
* @param toJson Returns the full JSON response if `true`. * @param toJson Returns the full JSON response if `true`.
@ -73,7 +72,6 @@ open class Bitlinks(private val accessToken: String) {
bitlink: String, bitlink: String,
unit: Units = Units.DAY, unit: Units = Units.DAY,
units: Int = -1, units: Int = -1,
size: Int = 50,
unit_reference: String = Constants.EMPTY, unit_reference: String = Constants.EMPTY,
toJson: Boolean = false toJson: Boolean = false
): String { ): String {
@ -85,8 +83,7 @@ open class Bitlinks(private val accessToken: String) {
mapOf( mapOf(
"unit" to unit.toString().lowercase(), "unit" to unit.toString().lowercase(),
"units" to units.toString(), "units" to units.toString(),
"size" to size.toString(), "unit_reference" to URLEncoder.encode(unit_reference, StandardCharsets.UTF_8)
"unit_reference" to unit_reference
), ),
Methods.GET Methods.GET
) )
@ -106,12 +103,12 @@ open class Bitlinks(private val accessToken: String) {
@Synchronized @Synchronized
fun create(config: CreateConfig): String { fun create(config: CreateConfig): String {
return create( return create(
config.long_url,
config.domain, config.domain,
config.title,
config.group_guid, config.group_guid,
config.title,
config.tags, config.tags,
config.deepLinks, config.deepLinks,
config.long_url,
config.toJson config.toJson
) )
} }
@ -121,20 +118,20 @@ open class Bitlinks(private val accessToken: String) {
* *
* See the [Bit.ly API](https://dev.bitly.com/api-reference#createFullBitlink) for more information. * See the [Bit.ly API](https://dev.bitly.com/api-reference#createFullBitlink) for more information.
* *
* @param long_url The long URL.
* @param domain A branded short domain or `bit.ly` by default. * @param domain A branded short domain or `bit.ly` by default.
* @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 toJson Returns the full JSON response if `true`. * @param toJson Returns the full JSON response if `true`.
* @return The shortened URL or an empty string on error. * @return The shortened URL or an empty string on error.
*/ */
@Synchronized @Synchronized
fun create( fun create(
long_url: String,
domain: String = Constants.EMPTY, domain: String = Constants.EMPTY,
title: String = Constants.EMPTY,
group_guid: String = Constants.EMPTY, group_guid: String = Constants.EMPTY,
title: String = Constants.EMPTY,
tags: Array<String> = emptyArray(), tags: Array<String> = emptyArray(),
deeplinks: Array<Map<String, String>> = emptyArray(), deeplinks: Array<Map<String, String>> = emptyArray(),
long_url: String,
toJson: Boolean = false toJson: Boolean = false
): String { ): String {
var link = if (toJson) Constants.EMPTY_JSON else Constants.EMPTY var link = if (toJson) Constants.EMPTY_JSON else Constants.EMPTY
@ -144,8 +141,8 @@ open class Bitlinks(private val accessToken: String) {
"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 (group_guid.isNotBlank()) put("group_guid", group_guid) if (group_guid.isNotBlank()) put("group_guid", group_guid)
if (title.isNotBlank()) put("title", title)
if (tags.isNotEmpty()) put("tags", tags) if (tags.isNotEmpty()) put("tags", tags)
if (deeplinks.isNotEmpty()) put("deeplinks", deeplinks) if (deeplinks.isNotEmpty()) put("deeplinks", deeplinks)
} }
@ -211,8 +208,8 @@ open class Bitlinks(private val accessToken: String) {
* See the [Bit.ly API](https://dev.bitly.com/api-reference#createBitlink) for more information. * See the [Bit.ly API](https://dev.bitly.com/api-reference#createBitlink) for more information.
* *
* @param long_url The long URL. * @param long_url The long URL.
* @param group_guid A GUID for a Bitly group.
* @param domain A branded short domain or `bit.ly` by default. * @param domain A branded short domain or `bit.ly` by default.
* @param group_guid A GUID for a Bitly group.
* @param toJson Returns the full JSON response if `true`. * @param toJson Returns the full JSON response if `true`.
* @return The short URL or the [long_url] on error. * @return The short URL or the [long_url] on error.
*/ */
@ -220,8 +217,8 @@ open class Bitlinks(private val accessToken: String) {
@JvmOverloads @JvmOverloads
fun shorten( fun shorten(
long_url: String, long_url: String,
group_guid: String = Constants.EMPTY,
domain: String = Constants.EMPTY, domain: String = Constants.EMPTY,
group_guid: String = Constants.EMPTY,
toJson: Boolean = false toJson: Boolean = false
): String { ): String {
var bitlink = if (toJson) Constants.EMPTY_JSON else long_url var bitlink = if (toJson) Constants.EMPTY_JSON else long_url
@ -231,8 +228,8 @@ open class Bitlinks(private val accessToken: String) {
} }
} else { } else {
val params = mutableMapOf("long_url" to long_url).apply { val params = mutableMapOf("long_url" to long_url).apply {
if (group_guid.isNotBlank()) put("group_guid", group_guid)
if (domain.isNotBlank()) put("domain", domain) if (domain.isNotBlank()) put("domain", domain)
if (group_guid.isNotBlank()) put("group_guid", group_guid)
} }
lastCallResponse = Utils.call(accessToken, "shorten".toEndPoint(), params) lastCallResponse = Utils.call(accessToken, "shorten".toEndPoint(), params)
@ -256,18 +253,10 @@ open class Bitlinks(private val accessToken: String) {
fun update(config: UpdateConfig): String { fun update(config: UpdateConfig): String {
return update( return update(
config.bitlink, config.bitlink,
config.references, config.title,
config.archived, config.archived,
config.tags, config.tags,
config.created_at,
config.title,
config.deepLinks, config.deepLinks,
config.created_by,
config.long_url,
config.client_id,
config.custom_bitlinks,
config.link,
config.id,
config.toJson config.toJson
) )
} }
@ -284,36 +273,20 @@ open class Bitlinks(private val accessToken: String) {
@Synchronized @Synchronized
fun update( fun update(
bitlink: String, bitlink: String,
references: Map<String, String> = emptyMap(), title: String = Constants.EMPTY,
archived: Boolean = false, archived: Boolean = false,
tags: Array<String> = emptyArray(), tags: Array<String> = emptyArray(),
created_at: String = Constants.EMPTY,
title: String = Constants.EMPTY,
deeplinks: Array<Map<String, String>> = emptyArray(), deeplinks: Array<Map<String, String>> = emptyArray(),
created_by: String = Constants.EMPTY,
long_url: String = Constants.EMPTY,
client_id: String = Constants.EMPTY,
custom_bitlinks: Array<String> = emptyArray(),
link: String = Constants.EMPTY,
id: String = Constants.EMPTY,
toJson: Boolean = false toJson: Boolean = false
): String { ): 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 (title.isNotBlank()) put("title", title)
if (archived) put("archived", true) if (archived) put("archived", true)
if (tags.isNotEmpty()) put("tags", tags) if (tags.isNotEmpty()) put("tags", tags)
if (created_at.isNotBlank()) put("created_at", created_at)
if (title.isNotBlank()) put("title", title)
if (deeplinks.isNotEmpty()) put("deeplinks", deeplinks) if (deeplinks.isNotEmpty()) put("deeplinks", deeplinks)
if (created_by.isNotBlank()) put("created_by", created_by)
if (long_url.isNotBlank()) put("long_url", long_url)
if (client_id.isNotBlank()) put("client_id", client_id)
if (custom_bitlinks.isNotEmpty()) put("custom_bitlinks", custom_bitlinks)
if (link.isNotBlank()) put("link", link)
if (id.isNotBlank()) put("id", id)
}, },
Methods.PATCH Methods.PATCH
) )

View file

@ -36,46 +36,67 @@ import net.thauvin.erik.bitly.Constants
/** /**
* Provides a builder to create a Bitlink. * Provides a builder to create a Bitlink.
*/ */
class CreateConfig private constructor( class CreateConfig private constructor(builder: Builder) {
val domain: String, val domain: String
val title: String, val group_guid: String
val group_guid: String, val title: String
val tags: Array<String>, val tags: Array<String>
val deepLinks: Array<Map<String, String>>, val deepLinks: Array<Map<String, String>>
val long_url: String, val long_url: String
val toJson: Boolean val toJson: Boolean
) {
init {
domain = builder.domain
group_guid = builder.group_guid
title = builder.title
tags = builder.tags
deepLinks = builder.deeplinks
long_url = builder.long_url
toJson = builder.toJson
}
/** /**
* Configures the creation parameters of a Bitlink. * Configures the creation parameters of a Bitlink.
* *
* See the [Bit.ly API](https://dev.bitly.com/api-reference#createFullBitlink) for more information. * See the [Bit.ly API](https://dev.bitly.com/api-reference#createFullBitlink) for more information.
**/ **/
@Suppress("ArrayInDataClass") data class Builder(var long_url: String) {
data class Builder( var domain: String = Constants.EMPTY
private var domain: String = Constants.EMPTY, var group_guid: String = Constants.EMPTY
private var title: String = Constants.EMPTY, var title: String = Constants.EMPTY
private var group_guid: String = Constants.EMPTY, var tags: Array<String> = emptyArray()
private var tags: Array<String> = emptyArray(), var deeplinks: Array<Map<String, String>> = emptyArray()
private var deeplinks: Array<Map<String, String>> = emptyArray(), var toJson: Boolean = false
private var long_url: String = Constants.EMPTY,
private var toJson: Boolean = false /**
) { * A branded short domain or `bit.ly` by default.
*/
fun domain(domain: String) = apply { this.domain = domain } fun domain(domain: String) = apply { this.domain = domain }
fun title(title: String) = apply { this.title = title }
/**
* Always include a specific group and custom domain in your shorten calls.
*/
fun groupGuid(group_guid: String) = apply { this.group_guid = group_guid } fun groupGuid(group_guid: String) = apply { this.group_guid = group_guid }
fun title(title: String) = apply { this.title = title }
fun tags(tags: Array<String>) = apply { this.tags = tags } fun tags(tags: Array<String>) = apply { this.tags = tags }
fun deeplinks(deeplinks: Array<Map<String, String>>) = apply { this.deeplinks = deeplinks } fun deeplinks(deeplinks: Array<Map<String, String>>) = apply { this.deeplinks = deeplinks }
/**
* The long URL.
*/
fun longUrl(long_url: String) = apply { this.long_url = long_url } fun longUrl(long_url: String) = apply { this.long_url = long_url }
/**
* Returns the full JSON response if `true`.
*/
fun toJson(toJson: Boolean) = apply { this.toJson = toJson } fun toJson(toJson: Boolean) = apply { this.toJson = toJson }
fun build() = CreateConfig( /**
domain, * Builds the configuration.
title, */
group_guid, fun build() = CreateConfig(this)
tags,
deeplinks,
long_url,
toJson
)
} }
} }

View file

@ -36,74 +36,53 @@ import net.thauvin.erik.bitly.Constants
/** /**
* Provides a builder to update a Bitlink. * Provides a builder to update a Bitlink.
*/ */
class UpdateConfig private constructor( class UpdateConfig private constructor(builder: Builder) {
val bitlink: String, val bitlink: String
val references: Map<String, String>, val title: String
val archived: Boolean, val archived: Boolean
val tags: Array<String>, val tags: Array<String>
val created_at: String, val deepLinks: Array<Map<String, String>>
val title: String, val toJson: Boolean
val deepLinks: Array<Map<String, String>>,
val created_by: String, init {
val long_url: String, bitlink = builder.bitlink
val client_id: String, title = builder.title
val custom_bitlinks: Array<String>, archived = builder.archived
val link: String, tags = builder.tags
val id: String, deepLinks = builder.deeplinks
val toJson: Boolean, toJson = builder.toJson
) { }
/** /**
* Configures the update parameters of a Bitlink. * Configures the update parameters of a 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.
**/ **/
@Suppress("ArrayInDataClass") data class Builder(var bitlink: String) {
data class Builder( var title: String = Constants.EMPTY
private var bitlink: String = Constants.EMPTY, var archived: Boolean = false
private var references: Map<String, String> = emptyMap(), var tags: Array<String> = emptyArray()
private var archived: Boolean = false, var deeplinks: Array<Map<String, String>> = emptyArray()
private var tags: Array<String> = emptyArray(), var toJson: Boolean = false
private var created_at: String = Constants.EMPTY,
private var title: String = Constants.EMPTY, /**
private var deeplinks: Array<Map<String, String>> = emptyArray(), * A Bitlink made of the domain and hash.
private var created_by: String = Constants.EMPTY, */
private var long_url: String = Constants.EMPTY,
private var client_id: String = Constants.EMPTY,
private var custom_bitlinks: Array<String> = emptyArray(),
private var link: String = Constants.EMPTY,
private var id: String = Constants.EMPTY,
private var toJson: Boolean = false
) {
fun bitlink(bitlink: String) = apply { this.bitlink = bitlink } fun bitlink(bitlink: String) = apply { this.bitlink = bitlink }
fun references(references: Map<String, String>) = apply { this.references = references }
fun title(title: String) = apply { this.title = title }
fun archived(archived: Boolean) = apply { this.archived = archived } fun archived(archived: Boolean) = apply { this.archived = archived }
fun tags(tags: Array<String>) = apply { this.tags = tags } fun tags(tags: Array<String>) = apply { this.tags = tags }
fun createdAt(createdAt: String) = apply { this.created_at = createdAt }
fun title(title: String) = apply { this.title = title }
fun deepLinks(deepLinks: Array<Map<String, String>>) = apply { this.deeplinks = deepLinks } fun deepLinks(deepLinks: Array<Map<String, String>>) = apply { this.deeplinks = deepLinks }
fun createdBy(createdBy: String) = apply { this.created_by = createdBy }
fun longUrl(longUrl: String) = apply { this.long_url = longUrl } /**
fun clientId(clientId: String) = apply { this.client_id = clientId } * Returns the full JSON response if `true`.
fun customBitlinks(customBitlinks: Array<String>) = apply { this.custom_bitlinks = customBitlinks } */
fun link(link: String) = apply { this.link = link }
fun id(id: String) = apply { this.id = id }
fun toJson(toJson: Boolean) = apply { this.toJson = toJson } fun toJson(toJson: Boolean) = apply { this.toJson = toJson }
fun build() = UpdateConfig( /**
bitlink, * Builds the configuration.
references, */
archived, fun build() = UpdateConfig(this)
tags,
created_at,
title,
deeplinks,
created_by,
long_url,
client_id,
custom_bitlinks,
link,
id,
toJson
)
} }
} }

View file

@ -200,15 +200,15 @@ class BitlyTest {
@Test @Test
fun `create bitlink with config`() { fun `create bitlink with config`() {
var config = CreateConfig.Builder().longUrl(longUrl).build() var config = CreateConfig.Builder(longUrl).build()
assertThat(bitly.bitlinks().create(config), "create(config)") assertThat(bitly.bitlinks().create(config), "create(config)")
.matches("https://\\w+.\\w{2}/\\w{7}".toRegex()) .matches("https://\\w+.\\w{2}/\\w{7}".toRegex())
config = CreateConfig.Builder() config = CreateConfig.Builder(longUrl)
.domain("bit.ly") .domain("bit.ly")
.title("Erik's Blog") .title("Erik's Blog")
.tags(arrayOf("erik", "thauvin", "blog", "weblog")) .tags(arrayOf("erik", "thauvin", "blog", "weblog"))
.longUrl(longUrl).build() .build()
assertEquals( assertEquals(
shortUrl, shortUrl,
bitly.bitlinks().create(config) bitly.bitlinks().create(config)
@ -237,18 +237,12 @@ class BitlyTest {
assertThat(bl.update(shortUrl, tags = emptyArray(), toJson = true), "update(tags)") assertThat(bl.update(shortUrl, tags = emptyArray(), toJson = true), "update(tags)")
.contains("\"tags\":[]") .contains("\"tags\":[]")
bl.update(shortUrl, link = longUrl)
assertThat(bl.lastCallResponse).prop(CallResponse::isSuccessful).isTrue()
assertEquals(Constants.FALSE, bl.update("bit.ly/407GjJU", id = "foo"))
} }
@Test @Test
fun `update bitlink with config`() { fun `update bitlink with config`() {
val bl = bitly.bitlinks() val bl = bitly.bitlinks()
var config = UpdateConfig.Builder() var config = UpdateConfig.Builder(shortUrl)
.bitlink(shortUrl)
.title("Erik's Weblog") .title("Erik's Weblog")
.tags(arrayOf("blog", "weblog")) .tags(arrayOf("blog", "weblog"))
.archived(true) .archived(true)
@ -256,19 +250,11 @@ class BitlyTest {
assertEquals(Constants.TRUE, bl.update(config)) assertEquals(Constants.TRUE, bl.update(config))
config = UpdateConfig.Builder() config = UpdateConfig.Builder(shortUrl)
.bitlink(shortUrl)
.toJson(true) .toJson(true)
.build() .build()
assertThat(bl.update(config), "update(tags)").contains("\"tags\":[]") assertThat(bl.update(config), "update(tags)").contains("\"tags\":[]")
config = UpdateConfig.Builder()
.bitlink(shortUrl)
.link(longUrl)
.build()
assertEquals(Constants.TRUE, bl.update(config))
} }
@Test @Test