Skip to content

Commit

Permalink
Attachments API Support (#171)
Browse files Browse the repository at this point in the history
# Description
This PR adds support for the Attachments API

# License
<!-- Your PR comment must contain the following line for us to merge the
PR. -->
I confirm that this contribution is made under the terms of the MIT
license and that I have the authority necessary to make this
contribution on behalf of its copyright owner.
  • Loading branch information
mrashed-dev authored Nov 21, 2023
1 parent 97254ff commit 1424840
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Added support for the free-busy endpoint
* Added Messages, Drafts, and Smart Compose APIs support
* Added support for custom authentication, connectors, and credentials APIs
* Added support for attachments API

### Changed
* Return webhook object with secret when creating a webhook
Expand Down
58 changes: 40 additions & 18 deletions src/main/kotlin/com/nylas/NylasClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ class NylasClient(
return Applications(this)
}

/**
* Access the Attachments API
* @return The Attachments API
*/
fun attachments(): Attachments {
return Attachments(this)
}

/**
* Access the Auth API
* @return The Auth API
Expand Down Expand Up @@ -168,7 +176,7 @@ class NylasClient(
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executeGet(
path: String,
resultType: Type? = null,
resultType: Type,
queryParams: IQueryParams? = null,
): T {
val url = buildUrl(path, queryParams)
Expand All @@ -186,7 +194,7 @@ class NylasClient(
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executePut(
path: String,
resultType: Type? = null,
resultType: Type,
requestBody: String? = null,
queryParams: IQueryParams? = null,
): T {
Expand All @@ -206,7 +214,7 @@ class NylasClient(
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executePatch(
path: String,
resultType: Type? = null,
resultType: Type,
requestBody: String? = null,
queryParams: IQueryParams? = null,
): T {
Expand All @@ -226,7 +234,7 @@ class NylasClient(
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executePost(
path: String,
resultType: Type? = null,
resultType: Type,
requestBody: String? = null,
queryParams: IQueryParams? = null,
): T {
Expand All @@ -248,7 +256,7 @@ class NylasClient(
@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun <T> executeDelete(
path: String,
resultType: Type? = null,
resultType: Type,
queryParams: IQueryParams? = null,
): T {
val url = buildUrl(path, queryParams)
Expand All @@ -269,7 +277,7 @@ class NylasClient(
path: String,
method: HttpMethod,
requestBody: RequestBody,
resultType: Type? = null,
resultType: Type,
queryParams: IQueryParams? = null,
): T {
val url = buildUrl(path, queryParams)
Expand Down Expand Up @@ -299,22 +307,36 @@ class NylasClient(
url: HttpUrl.Builder,
method: HttpMethod,
body: RequestBody?,
resultType: Type?,
resultType: Type,
): T {
val responseBody = this.executeRequestRawResponse(url, method, body)
val adapter = JsonHelper.moshi().adapter<T>(resultType)
val serializedObject = adapter?.fromJson(responseBody.source()) ?: throw Exception("Failed to deserialize response body")
responseBody.close()
return serializedObject
}

@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
fun downloadResponse(
path: String,
queryParams: IQueryParams? = null,
): ResponseBody {
val url = buildUrl(path, queryParams)
return this.executeRequestRawResponse(url, HttpMethod.GET, null)
}

@Throws(AbstractNylasApiError::class, NylasSdkTimeoutError::class)
private fun executeRequestRawResponse(
url: HttpUrl.Builder,
method: HttpMethod,
body: RequestBody?,
): ResponseBody {
val request = buildRequest(url, method, body)
val finalUrl = url.build()
try {
httpClient.newCall(request).execute().use { response ->
throwAndCloseOnFailedRequest(finalUrl, response)
val responseBody = response.body()
if (resultType == null || responseBody == null) {
throw Exception("Unexpected null response body")
}

val adapter = JsonHelper.moshi().adapter<T>(resultType)

return adapter?.fromJson(responseBody.source()) ?: throw Exception("Failed to deserialize response body")
}
val response = httpClient.newCall(request).execute()
throwAndCloseOnFailedRequest(finalUrl, response)
return response.body() ?: throw Exception("Unexpected null response body")
} catch (e: SocketTimeoutException) {
throw NylasSdkTimeoutError(finalUrl.toString(), httpClient.callTimeoutMillis())
}
Expand Down
30 changes: 30 additions & 0 deletions src/main/kotlin/com/nylas/models/FindAttachmentQueryParams.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.nylas.models

import com.squareup.moshi.Json

/**
* Class representation of the query parameters for finding an attachment.
*/
data class FindAttachmentQueryParams(
/**
* Message ID to find the attachment in.
*/
@Json(name = "message_id")
val messageId: String,
) : IQueryParams {
/**
* Builder for [FindEventQueryParams].
* @property messageId Message ID to find the attachment in.
*/
data class Builder(
private val messageId: String,
) {
/**
* Builds a new [FindEventQueryParams] instance.
* @return [FindEventQueryParams]
*/
fun build() = FindEventQueryParams(
messageId,
)
}
}
63 changes: 63 additions & 0 deletions src/main/kotlin/com/nylas/resources/Attachments.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.nylas.resources

import com.nylas.NylasClient
import com.nylas.models.*
import okhttp3.ResponseBody

/**
* Nylas Attachments API
*
* The Nylas Attachments API allows you to fetch attachment metadata and download data.
*
* @param client The configured Nylas API client
*/
class Attachments(client: NylasClient) : Resource<Attachment>(client, Attachment::class.java) {
/**
* Return metadata of an attachment
* @param identifier Grant ID or email account to query
* @param attachmentId The id of the attachment to retrieve.
* @param queryParams The query parameters to include in the request
* @return The attachment metadata
*/
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun find(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams): Response<Attachment> {
val path = String.format("v3/grants/%s/attachments/%s", identifier, attachmentId)
return findResource(path, queryParams)
}

/**
* Download the attachment data
*
* This method returns a [ResponseBody] which can be used to stream the attachment data,
* and exposes useful headers such as the content type and content length.
* **NOTE**: The caller is responsible for closing the response body.
*
* Alternatively, you can use [downloadBytes] to download the attachment as a byte array.
*
* @param identifier Grant ID or email account to query
* @param attachmentId The id of the attachment to download.
* @param queryParams The query parameters to include in the request
* @return The [ResponseBody] containing the file data
*/
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun download(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams): ResponseBody {
val path = String.format("v3/grants/%s/attachments/%s/download", identifier, attachmentId)

return client.downloadResponse(path, queryParams)
}

/**
* Download the attachment as a byte array
* @param identifier Grant ID or email account to query
* @param attachmentId The id of the attachment to download.
* @param queryParams The query parameters to include in the request
* @return The raw file data
*/
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun downloadBytes(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams): ByteArray {
val download = download(identifier, attachmentId, queryParams)
val fileBytes = download.bytes()
download.close()
return fileBytes
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/com/nylas/resources/Auth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class Auth(private val client: NylasClient) {
@Throws(NylasOAuthError::class, NylasSdkTimeoutError::class)
fun revoke(token: String): Boolean {
val path = "v3/connect/revoke?token=$token"
client.executePost<Any>(path)
client.executePost<Any>(path, MutableMap::class.java)

return true
}
Expand Down

0 comments on commit 1424840

Please sign in to comment.