Files API support
AlexisBRENON opened this issue · comments
I try to upload the result of a spark job a CSV excerpt of a slack dataframe to a slack channel.
I think the best solution would be to upload it as a file, through the files.upload
method
As described in the "Low-level HTTP API to Slack Web API" section, I declared my request and response objects:
package org.latestbit.slack.morphism.client.reqresp.files
import org.latestbit.slack.morphism.common.{SlackChannelId, SlackTs}
import org.latestbit.slack.morphism.files.SlackFile
case class SlackApiFilesUploadRequest(channels: Option[Seq[SlackChannelId]] = None,
file: Option[String] = None,
content: Option[String] = None,
filename: Option[String] = None,
filetype: Option[String] = None,
initialComment: Option[String] = None,
thread_ts: Option[SlackTs] = None,
title: Option[String] = None
)
case class SlackApiFilesUploadResponse(ts: SlackTs, file: SlackFile)
With SlackFile
defined as:
package org.latestbit.slack.morphism.files
import org.latestbit.slack.morphism.common.{SlackChannelId, SlackUserId}
case class SlackFile(id: Option[String],
created: Option[Long],
timestamp: Option[Long],
name: Option[String],
title: Option[String],
mimetype: Option[String],
filetype: Option[String],
pretty_type: Option[String],
user: Option[String],
editable: Option[Boolean],
size: Option[Long],
mode: Option[String],
is_external: Option[Boolean],
external_type: Option[String],
is_public: Option[Boolean],
public_url_shared: Option[Boolean],
display_as_bot: Option[Boolean],
username: Option[String],
url_private: Option[String],
url_private_download: Option[String],
thumb_64: Option[String],
thumb_80: Option[String],
thumb_360: Option[String],
thumb_360_w: Option[Int],
thumb_360_h: Option[Int],
thumb_160: Option[String],
thumb_360_gif: Option[String],
image_exif_rotation: Option[Int],
original_w: Option[Int],
original_h: Option[Int],
deanimate_gif: Option[String],
pjpeg: Option[String],
permalink: Option[String],
permalink_public: Option[String],
comments_count: Option[Int],
is_starred: Option[Boolean],
shares: Option[SlackShares],
channels: Option[Seq[SlackChannelId]],
groups: Option[Seq[String]],
ims: Option[Seq[String]],
has_rich_preview: Option[Boolean]
)
case class SlackShares(public: Map[SlackChannelId, Seq[SlackShare]])
case class SlackShare(reply_user: Seq[SlackUserId],
reply_users_count: Int,
reply_count: Int,
ts: String,
thread_ts: String,
latest_reply: String,
channel_name: String,
team_id: String)
And declare a package method to use them:
package org.latestbit.slack.morphism.client.reqresp
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import org.latestbit.slack.morphism.client.{SlackApiClientBackend, SlackApiClientError, SlackApiClientT, SlackApiToken}
import scala.concurrent.Future
package object files {
def upload(client: SlackApiClientT[Future])(
req: SlackApiFilesUploadRequest,
)(implicit
slackApiToken: SlackApiToken,
backendType: SlackApiClientBackend.BackendType[Future]
): Future[Either[SlackApiClientError, SlackApiFilesUploadResponse]] = {
implicit val rqstEncoder: Encoder[SlackApiFilesUploadRequest] = deriveEncoder[SlackApiFilesUploadRequest]
implicit val rspDecoder: Decoder[SlackApiFilesUploadResponse] = deriveDecoder[SlackApiFilesUploadResponse]
client.http.post[SlackApiFilesUploadRequest, SlackApiFilesUploadResponse](
methodUri = "files.upload",
req = req,
)
}
}
However, when compiling this package.scala
file I get the following error:
.../src/main/scala/org/latestbit/slack/morphism/client/reqresp/files/package.scala:16:82
could not find Lazy implicit value of type io.circe.generic.encoding.DerivedAsObjectEncoder[org.latestbit.slack.morphism.client.reqresp.files.SlackApiFilesUploadRequest]
implicit val rqstEncoder: Encoder[SlackApiFilesUploadRequest] = deriveEncoder[SlackApiFilesUploadRequest]
.../src/main/scala/org/latestbit/slack/morphism/client/reqresp/files/package.scala:16:82
not enough arguments for method deriveEncoder: (implicit encode: shapeless.Lazy[io.circe.generic.encoding.DerivedAsObjectEncoder[org.latestbit.slack.morphism.client.reqresp.files.SlackApiFilesUploadRequest]])io.circe.Encoder.AsObject[org.latestbit.slack.morphism.client.reqresp.files.SlackApiFilesUploadRequest].
Unspecified value parameter encode.
implicit val rqstEncoder: Encoder[SlackApiFilesUploadRequest] = deriveEncoder[SlackApiFilesUploadRequest]
.../src/main/scala/org/latestbit/slack/morphism/client/reqresp/files/package.scala:17:82
could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[org.latestbit.slack.morphism.client.reqresp.files.SlackApiFilesUploadResponse]
implicit val rspDecoder: Decoder[SlackApiFilesUploadResponse] = deriveDecoder[SlackApiFilesUploadResponse]
.../src/main/scala/org/latestbit/slack/morphism/client/reqresp/files/package.scala:17:82
not enough arguments for method deriveDecoder: (implicit decode: shapeless.Lazy[io.circe.generic.decoding.DerivedDecoder[org.latestbit.slack.morphism.client.reqresp.files.SlackApiFilesUploadResponse]])io.circe.Decoder[org.latestbit.slack.morphism.client.reqresp.files.SlackApiFilesUploadResponse].
Unspecified value parameter decode.
implicit val rspDecoder: Decoder[SlackApiFilesUploadResponse] = deriveDecoder[SlackApiFilesUploadResponse]
Is there any plan to support the files.[...]
methods?
Is there any workaround to make it work for the moment?
Hey, as a first glance, try this:
- extend your object
files
withorg.latestbit.slack.morphism.codecs.CirceCodecs
to bring all existing JSON codecs - you need to define encoder/decoders for all of the new classes that you have in SlackApiFilesUploadRequest/SlackApiFilesUploadResponse (in their fields), so you need to define Circe encoder/decoders for SlackShare, etc as well
I'll think about to support it natively, for now try those
All info I just gave were relavant for Slack Web API that supports JSON requests.
Now I checked https://api.slack.com/methods/files.upload, and unfortunately, it won't work, because this method requires:
multipart/form-data
or application/x-www-form-urlencoded
, so it needs to be handled a bit differently and Circe codecs won't help for the request part.
This method does not currently accept application/json
So, give me time to dig into it more.
Started working on this, it is needed handled a bit differently than other WebAPI methods
In the latest snapshot (3.1.0-SNAPSHOT) there is a working version of files.upload
method. I think in a few days it will be released with some other Files API methods. I tested it a bit, seems working fine now.
v3.1.0 released with the support of Files API.
Wow ! What a responsiveness. Thanks you !