/** * Generated by API Builder - https://www.apibuilder.io * Service version: 0.0.1-dev * User agent: apibuilder app.apibuilder.io/teambytes/hipchat-sns-bridge/0.0.1-dev/http4s_0_18 */ package com.teambytes.hipchat.sns.bridge.v0.models { /** * A request semantic failure reason. */ final case class Error( description: String ) /** * @param scopes An array of scopes that are required to consume the HipChat API. * @param fromName The name that messages should be from when sent from the integration itself. */ final case class HipchatApiConsumer( scopes: Seq[com.teambytes.hipchat.sns.bridge.v0.models.HipchatScope], fromName: _root_.scala.Option[String] = None ) /** * @param configurable Most integrations will need to be configured in order to work correctly. For * this purpose, an integration can expose a 'configurable' capability that * provides an HTML page to be included as a panel in the configuration dialog. * @param hipchatApiConsumer The ability to consume the HipChat API. * @param installable The capability of receiving a synchronous installation callback during * integration installation. * @param oauth2Provider The capability of providing and accepting OAuth 2 tokens for authentication. */ final case class HipchatCapabilities( configurable: _root_.scala.Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatConfigurationPage] = None, hipchatApiConsumer: _root_.scala.Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatApiConsumer] = None, installable: _root_.scala.Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatInstallable] = None, oauth2Provider: _root_.scala.Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatOauth2Provider] = None ) /** * @param name The display name of this application. * @param description A short description of this application. * @param key The marketplace integration key that uniquely identifies the application, if * registered. * @param apiVersion The HipChat Connect API version used by this integration. Defaults to 1:1. * @param capabilities The set of capabilities this application supports. * @param links URLs to retrieve this and related integration information. * @param vendor The vendor that maintains this application. */ final case class HipchatCapabilitiesDescriptor( name: String, description: String, key: String, apiVersion: _root_.scala.Option[String] = None, capabilities: _root_.scala.Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilities] = None, links: com.teambytes.hipchat.sns.bridge.v0.models.HipchatLinks, vendor: _root_.scala.Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatVendor] = None ) /** * @param allowAccessToRoomAdmins If the add-on is installed globally, this property can allow the configuration * page to be accessed in the room administration pages making it possible to have * room specific configuration for the global add-on. This is only valid for * globally installed add-ons. * @param url The URL to embed into a configure dialog via an iframe. */ final case class HipchatConfigurationPage( allowAccessToRoomAdmins: _root_.scala.Option[String] = None, url: String ) final case class HipchatInstallData( capabilitiesUrl: String, oauthId: String, oauthSecret: String, groupId: Long, roomId: _root_.scala.Option[String] = None ) /** * @param callbackUrl The URL to receive a confirmation of an integration installation. * @param installedUrl The URL HipChat will redirect to post-installation. * @param allowGlobal Whether the integration can be installed globally or not. * @param allowRoom Whether the integration can be installed in a room or not. */ final case class HipchatInstallable( callbackUrl: _root_.scala.Option[String] = None, installedUrl: _root_.scala.Option[String] = None, allowGlobal: _root_.scala.Option[Boolean] = None, allowRoom: _root_.scala.Option[Boolean] = None ) /** * @param homepage The URL to human-viewable home page of this integration. * @param api The URL to the REST API root. * @param self The URL to this descriptor. */ final case class HipchatLinks( homepage: _root_.scala.Option[String] = None, api: _root_.scala.Option[String] = None, self: String ) /** * @param tokenUrl The OAuth 2 token endpoint for retrieving an access token. * @param authorizationUrl The OAuth 2 endpoint to direct browsers to in order to receive an authorization * code that can be later exchanged using the token URL for an access token. */ final case class HipchatOauth2Provider( tokenUrl: _root_.scala.Option[String] = None, authorizationUrl: _root_.scala.Option[String] = None ) /** * @param name The vendor display name. * @param url The vendor's home page URL. */ final case class HipchatVendor( name: String, url: String ) /** * @param name Name of this service. * @param version Version of this service. * @param scalaVersion Version of Scala this service is using. * @param sbtVersion Version of SBT used to build this service. * @param buildTime Time the service was built at. */ final case class ServiceInfo( name: String, version: String, scalaVersion: String, sbtVersion: String, buildTime: _root_.java.time.Instant ) /** * @param `type` The type of message. For a unsubscribe confirmation, the type is * UnsubscribeConfirmation. * @param messageId A Universally Unique Identifier, unique for each message published. For a * message that Amazon SNS resends during a retry, the message ID of the original * message is used. * @param topicArn The Amazon Resource Name (ARN) for the topic that this endpoint has been * unsubscribed from. * @param message A string that describes the message. * @param timestamp The time (GMT) when the unsubscribe confirmation was sent. * @param signatureVersion Version of the Amazon SNS signature used. * @param signature Base64-encoded 'SHA1withRSA' signature of the Message, MessageId, Type, * Timestamp, and TopicArn values. * @param signingCertURL The URL to the certificate that was used to sign the message. * @param token A value you can use with the ConfirmSubscription action to re-confirm the * subscription. Alternatively, you can simply visit the SubscribeURL. * @param subject The Subject parameter specified when the notification was published to the * topic. Note that this is an optional parameter. If no Subject was specified, * then this name/value pair does not appear in this JSON document. * @param subscribeURL The URL that you must visit in order to re-confirm the subscription. * Alternatively, you can instead use the Token with the ConfirmSubscription action * to re-confirm the subscription. * @param unsubscribeURL A URL that you can use to unsubscribe the endpoint from this topic. If you visit * this URL, Amazon SNS unsubscribes the endpoint and stops sending notifications * to this endpoint. */ final case class SnsNotification( `type`: String, messageId: String, topicArn: String, message: String, timestamp: String, signatureVersion: String, signature: String, signingCertURL: String, token: _root_.scala.Option[String] = None, subject: _root_.scala.Option[String] = None, subscribeURL: _root_.scala.Option[String] = None, unsubscribeURL: _root_.scala.Option[String] = None ) /** * Your add-on must declare the scopes it requires based on which API endpoints it * needs to use, via its descriptor. */ sealed trait HipchatScope extends _root_.scala.Product with _root_.scala.Serializable object HipchatScope { case object SendMessage extends HipchatScope { override def toString = "send_message" } case object SendNotification extends HipchatScope { override def toString = "send_notification" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends HipchatScope /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[HipchatScope] = scala.List(SendMessage, SendNotification) private val byName: Map[String, HipchatScope] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): HipchatScope = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[HipchatScope] = byName.get(value.toLowerCase) } } package com.teambytes.hipchat.sns.bridge.v0.models { package object json { import io.circe.Decoder._ import io.circe.Encoder._ import scala.language.implicitConversions // See below - Make Scala 2.11 Either monadic import scala.util.Try import io.circe.{Json, JsonObject, Encoder, Decoder, DecodingFailure} import io.circe.syntax._ import com.teambytes.hipchat.sns.bridge.v0.models.json._ // Make Scala 2.11 Either monadic private[v0] implicit def eitherOps[A,B](e: Either[A,B]) = cats.implicits.catsSyntaxEither(e) private[v0] implicit val decodeUUID: Decoder[_root_.java.util.UUID] = Decoder.decodeString.emapTry(str => Try(_root_.java.util.UUID.fromString(str))) private[v0] implicit val encodeUUID: Encoder[_root_.java.util.UUID] = Encoder.encodeString.contramap[_root_.java.util.UUID](uuid => uuid.toString) private[v0] implicit val decodeInstant: Decoder[_root_.java.time.Instant] = Decoder.decodeString.emapTry(str => Try(_root_.java.time.OffsetDateTime.parse(str).toInstant)) private[v0] implicit val encodeInstant: Encoder[_root_.java.time.Instant] = Encoder.encodeString.contramap[_root_.java.time.Instant](_.toString) private[v0] implicit val decodeLocalDate: Decoder[_root_.java.time.LocalDate] = Decoder.decodeString.emapTry(str => Try(_root_.java.time.LocalDate.parse(str))) private[v0] implicit val encodeLocalDate: Encoder[_root_.java.time.LocalDate] = Encoder.encodeString.contramap[_root_.java.time.LocalDate](_.toString) implicit val jsonDecoderHipchatSnsBridgeHipchatScope: Decoder[com.teambytes.hipchat.sns.bridge.v0.models.HipchatScope] = Decoder.decodeString.map(com.teambytes.hipchat.sns.bridge.v0.models.HipchatScope(_)) implicit val jsonEncoderHipchatSnsBridgeHipchatScope: Encoder[com.teambytes.hipchat.sns.bridge.v0.models.HipchatScope] = Encoder.encodeString.contramap[com.teambytes.hipchat.sns.bridge.v0.models.HipchatScope](_.toString) implicit def decodeHipchatSnsBridgeError: Decoder[Error] = Decoder.instance { c => for { description <- c.downField("description").as[String] } yield { Error( description = description ) } } implicit def encodeHipchatSnsBridgeError: Encoder[Error] = Encoder.instance { t => Json.fromFields(Seq( Some("description" -> t.description.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatApiConsumer: Decoder[HipchatApiConsumer] = Decoder.instance { c => for { scopes <- c.downField("scopes").as[Seq[com.teambytes.hipchat.sns.bridge.v0.models.HipchatScope]] fromName <- c.downField("fromName").as[Option[String]] } yield { HipchatApiConsumer( scopes = scopes, fromName = fromName ) } } implicit def encodeHipchatSnsBridgeHipchatApiConsumer: Encoder[HipchatApiConsumer] = Encoder.instance { t => Json.fromFields(Seq( Some("scopes" -> t.scopes.asJson), t.fromName.map(t => "fromName" -> t.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatCapabilities: Decoder[HipchatCapabilities] = Decoder.instance { c => for { configurable <- c.downField("configurable").as[Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatConfigurationPage]] hipchatApiConsumer <- c.downField("hipchatApiConsumer").as[Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatApiConsumer]] installable <- c.downField("installable").as[Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatInstallable]] oauth2Provider <- c.downField("oauth2Provider").as[Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatOauth2Provider]] } yield { HipchatCapabilities( configurable = configurable, hipchatApiConsumer = hipchatApiConsumer, installable = installable, oauth2Provider = oauth2Provider ) } } implicit def encodeHipchatSnsBridgeHipchatCapabilities: Encoder[HipchatCapabilities] = Encoder.instance { t => Json.fromFields(Seq( t.configurable.map(t => "configurable" -> t.asJson), t.hipchatApiConsumer.map(t => "hipchatApiConsumer" -> t.asJson), t.installable.map(t => "installable" -> t.asJson), t.oauth2Provider.map(t => "oauth2Provider" -> t.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatCapabilitiesDescriptor: Decoder[HipchatCapabilitiesDescriptor] = Decoder.instance { c => for { name <- c.downField("name").as[String] description <- c.downField("description").as[String] key <- c.downField("key").as[String] apiVersion <- c.downField("apiVersion").as[Option[String]] capabilities <- c.downField("capabilities").as[Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilities]] links <- c.downField("links").as[com.teambytes.hipchat.sns.bridge.v0.models.HipchatLinks] vendor <- c.downField("vendor").as[Option[com.teambytes.hipchat.sns.bridge.v0.models.HipchatVendor]] } yield { HipchatCapabilitiesDescriptor( name = name, description = description, key = key, apiVersion = apiVersion, capabilities = capabilities, links = links, vendor = vendor ) } } implicit def encodeHipchatSnsBridgeHipchatCapabilitiesDescriptor: Encoder[HipchatCapabilitiesDescriptor] = Encoder.instance { t => Json.fromFields(Seq( Some("name" -> t.name.asJson), Some("description" -> t.description.asJson), Some("key" -> t.key.asJson), t.apiVersion.map(t => "apiVersion" -> t.asJson), t.capabilities.map(t => "capabilities" -> t.asJson), Some("links" -> t.links.asJson), t.vendor.map(t => "vendor" -> t.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatConfigurationPage: Decoder[HipchatConfigurationPage] = Decoder.instance { c => for { allowAccessToRoomAdmins <- c.downField("allowAccessToRoomAdmins").as[Option[String]] url <- c.downField("url").as[String] } yield { HipchatConfigurationPage( allowAccessToRoomAdmins = allowAccessToRoomAdmins, url = url ) } } implicit def encodeHipchatSnsBridgeHipchatConfigurationPage: Encoder[HipchatConfigurationPage] = Encoder.instance { t => Json.fromFields(Seq( t.allowAccessToRoomAdmins.map(t => "allowAccessToRoomAdmins" -> t.asJson), Some("url" -> t.url.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatInstallData: Decoder[HipchatInstallData] = Decoder.instance { c => for { capabilitiesUrl <- c.downField("capabilitiesUrl").as[String] oauthId <- c.downField("oauthId").as[String] oauthSecret <- c.downField("oauthSecret").as[String] groupId <- c.downField("groupId").as[Long] roomId <- c.downField("roomId").as[Option[String]] } yield { HipchatInstallData( capabilitiesUrl = capabilitiesUrl, oauthId = oauthId, oauthSecret = oauthSecret, groupId = groupId, roomId = roomId ) } } implicit def encodeHipchatSnsBridgeHipchatInstallData: Encoder[HipchatInstallData] = Encoder.instance { t => Json.fromFields(Seq( Some("capabilitiesUrl" -> t.capabilitiesUrl.asJson), Some("oauthId" -> t.oauthId.asJson), Some("oauthSecret" -> t.oauthSecret.asJson), Some("groupId" -> t.groupId.asJson), t.roomId.map(t => "roomId" -> t.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatInstallable: Decoder[HipchatInstallable] = Decoder.instance { c => for { callbackUrl <- c.downField("callbackUrl").as[Option[String]] installedUrl <- c.downField("installedUrl").as[Option[String]] allowGlobal <- c.downField("allowGlobal").as[Option[Boolean]] allowRoom <- c.downField("allowRoom").as[Option[Boolean]] } yield { HipchatInstallable( callbackUrl = callbackUrl, installedUrl = installedUrl, allowGlobal = allowGlobal, allowRoom = allowRoom ) } } implicit def encodeHipchatSnsBridgeHipchatInstallable: Encoder[HipchatInstallable] = Encoder.instance { t => Json.fromFields(Seq( t.callbackUrl.map(t => "callbackUrl" -> t.asJson), t.installedUrl.map(t => "installedUrl" -> t.asJson), t.allowGlobal.map(t => "allowGlobal" -> t.asJson), t.allowRoom.map(t => "allowRoom" -> t.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatLinks: Decoder[HipchatLinks] = Decoder.instance { c => for { homepage <- c.downField("homepage").as[Option[String]] api <- c.downField("api").as[Option[String]] self <- c.downField("self").as[String] } yield { HipchatLinks( homepage = homepage, api = api, self = self ) } } implicit def encodeHipchatSnsBridgeHipchatLinks: Encoder[HipchatLinks] = Encoder.instance { t => Json.fromFields(Seq( t.homepage.map(t => "homepage" -> t.asJson), t.api.map(t => "api" -> t.asJson), Some("self" -> t.self.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatOauth2Provider: Decoder[HipchatOauth2Provider] = Decoder.instance { c => for { tokenUrl <- c.downField("tokenUrl").as[Option[String]] authorizationUrl <- c.downField("authorizationUrl").as[Option[String]] } yield { HipchatOauth2Provider( tokenUrl = tokenUrl, authorizationUrl = authorizationUrl ) } } implicit def encodeHipchatSnsBridgeHipchatOauth2Provider: Encoder[HipchatOauth2Provider] = Encoder.instance { t => Json.fromFields(Seq( t.tokenUrl.map(t => "tokenUrl" -> t.asJson), t.authorizationUrl.map(t => "authorizationUrl" -> t.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeHipchatVendor: Decoder[HipchatVendor] = Decoder.instance { c => for { name <- c.downField("name").as[String] url <- c.downField("url").as[String] } yield { HipchatVendor( name = name, url = url ) } } implicit def encodeHipchatSnsBridgeHipchatVendor: Encoder[HipchatVendor] = Encoder.instance { t => Json.fromFields(Seq( Some("name" -> t.name.asJson), Some("url" -> t.url.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeServiceInfo: Decoder[ServiceInfo] = Decoder.instance { c => for { name <- c.downField("name").as[String] version <- c.downField("version").as[String] scalaVersion <- c.downField("scala_version").as[String] sbtVersion <- c.downField("sbt_version").as[String] buildTime <- c.downField("build_time").as[_root_.java.time.Instant] } yield { ServiceInfo( name = name, version = version, scalaVersion = scalaVersion, sbtVersion = sbtVersion, buildTime = buildTime ) } } implicit def encodeHipchatSnsBridgeServiceInfo: Encoder[ServiceInfo] = Encoder.instance { t => Json.fromFields(Seq( Some("name" -> t.name.asJson), Some("version" -> t.version.asJson), Some("scala_version" -> t.scalaVersion.asJson), Some("sbt_version" -> t.sbtVersion.asJson), Some("build_time" -> t.buildTime.asJson) ).flatten) } implicit def decodeHipchatSnsBridgeSnsNotification: Decoder[SnsNotification] = Decoder.instance { c => for { __type__ <- c.downField("Type").as[String] messageId <- c.downField("MessageId").as[String] topicArn <- c.downField("TopicArn").as[String] message <- c.downField("Message").as[String] timestamp <- c.downField("Timestamp").as[String] signatureVersion <- c.downField("SignatureVersion").as[String] signature <- c.downField("Signature").as[String] signingCertURL <- c.downField("SigningCertURL").as[String] token <- c.downField("Token").as[Option[String]] subject <- c.downField("Subject").as[Option[String]] subscribeURL <- c.downField("SubscribeURL").as[Option[String]] unsubscribeURL <- c.downField("UnsubscribeURL").as[Option[String]] } yield { SnsNotification( `type` = __type__, messageId = messageId, topicArn = topicArn, message = message, timestamp = timestamp, signatureVersion = signatureVersion, signature = signature, signingCertURL = signingCertURL, token = token, subject = subject, subscribeURL = subscribeURL, unsubscribeURL = unsubscribeURL ) } } implicit def encodeHipchatSnsBridgeSnsNotification: Encoder[SnsNotification] = Encoder.instance { t => Json.fromFields(Seq( Some("Type" -> t.`type`.asJson), Some("MessageId" -> t.messageId.asJson), Some("TopicArn" -> t.topicArn.asJson), Some("Message" -> t.message.asJson), Some("Timestamp" -> t.timestamp.asJson), Some("SignatureVersion" -> t.signatureVersion.asJson), Some("Signature" -> t.signature.asJson), Some("SigningCertURL" -> t.signingCertURL.asJson), t.token.map(t => "Token" -> t.asJson), t.subject.map(t => "Subject" -> t.asJson), t.subscribeURL.map(t => "SubscribeURL" -> t.asJson), t.unsubscribeURL.map(t => "UnsubscribeURL" -> t.asJson) ).flatten) } } } package com.teambytes.hipchat.sns.bridge.v0 { import cats.effect._ import cats.implicits._ import io.circe.syntax._ import scala.language.higherKinds object Constants { val BaseUrl = "http://hipchat-sns-bridge.common.giltaws.com" val Namespace = "com.teambytes.hipchat.sns.bridge.v0" val UserAgent = "apibuilder app.apibuilder.io/teambytes/hipchat-sns-bridge/0.0.1-dev/http4s_0_18" val Version = "0.0.1-dev" val VersionMajor = 0 } class Client[F[_]: Sync]( val baseUrl: org.http4s.Uri = org.http4s.Uri.unsafeFromString("http://hipchat-sns-bridge.common.giltaws.com"), auth: scala.Option[com.teambytes.hipchat.sns.bridge.v0.Authorization] = None, defaultHeaders: Seq[(String, String)] = Nil, httpClient: org.http4s.client.Client[F] ) extends interfaces.Client[F] { import org.http4s.Response import com.teambytes.hipchat.sns.bridge.v0.models.json._ def hipchatCapabilitiesDescriptors: HipchatCapabilitiesDescriptors[F] = HipchatCapabilitiesDescriptors def hipchatInstallData: HipchatInstallData[F] = HipchatInstallData def serviceInfo: ServiceInfo[F] = ServiceInfo def snsNotifications: SnsNotifications[F] = SnsNotifications object HipchatCapabilitiesDescriptors extends HipchatCapabilitiesDescriptors[F] { override def get( redirectToHipchatInstall: Boolean = false, requestHeaders: Seq[(String, String)] = Nil ): F[com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor] = { val urlPath = Seq("hipchat", "capabilities") val queryParameters = Seq( Some("redirect_to_hipchat_install" -> redirectToHipchatInstall.toString) ).flatten _executeRequest[Unit, com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor]("GET", path = urlPath, queryParameters = queryParameters, requestHeaders = requestHeaders) { case r if r.status.code == 200 => _root_.com.teambytes.hipchat.sns.bridge.v0.Client.parseJson[F, com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor]("com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor", r) case r => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Unsupported response code[${r.status.code}]. Expected: 200")) } } } object HipchatInstallData extends HipchatInstallData[F] { override def get( installableUrl: String, redirectUrl: String, requestHeaders: Seq[(String, String)] = Nil ): F[com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor] = { val urlPath = Seq("hipchat", "installable") val queryParameters = Seq( Some("installable_url" -> installableUrl), Some("redirect_url" -> redirectUrl) ).flatten _executeRequest[Unit, com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor]("GET", path = urlPath, queryParameters = queryParameters, requestHeaders = requestHeaders) { case r if r.status.code == 200 => _root_.com.teambytes.hipchat.sns.bridge.v0.Client.parseJson[F, com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor]("com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor", r) case r => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Unsupported response code[${r.status.code}]. Expected: 200")) } } override def post( hipchatInstallData: com.teambytes.hipchat.sns.bridge.v0.models.HipchatInstallData, requestHeaders: Seq[(String, String)] = Nil ): F[Unit] = { val urlPath = Seq("hipchat", "installable") val (payload, formPayload) = (Some(hipchatInstallData), None) _executeRequest[com.teambytes.hipchat.sns.bridge.v0.models.HipchatInstallData, Unit]("POST", path = urlPath, body = payload, formBody = formPayload, requestHeaders = requestHeaders) { case r if r.status.code == 200 => Sync[F].pure(()) case r => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Unsupported response code[${r.status.code}]. Expected: 200")) } } override def deleteByOauthId( oauthId: String, requestHeaders: Seq[(String, String)] = Nil ): F[Unit] = { val urlPath = Seq("hipchat", "installable", oauthId) _executeRequest[Unit, Unit]("DELETE", path = urlPath, requestHeaders = requestHeaders) { case r if r.status.code == 200 => Sync[F].pure(()) case r => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Unsupported response code[${r.status.code}]. Expected: 200")) } } } object ServiceInfo extends ServiceInfo[F] { override def get( requestHeaders: Seq[(String, String)] = Nil ): F[com.teambytes.hipchat.sns.bridge.v0.models.ServiceInfo] = { val urlPath = Seq("info") _executeRequest[Unit, com.teambytes.hipchat.sns.bridge.v0.models.ServiceInfo]("GET", path = urlPath, requestHeaders = requestHeaders) { case r if r.status.code == 200 => _root_.com.teambytes.hipchat.sns.bridge.v0.Client.parseJson[F, com.teambytes.hipchat.sns.bridge.v0.models.ServiceInfo]("com.teambytes.hipchat.sns.bridge.v0.models.ServiceInfo", r) case r => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Unsupported response code[${r.status.code}]. Expected: 200")) } } } object SnsNotifications extends SnsNotifications[F] { override def post( roomId: String, snsNotification: com.teambytes.hipchat.sns.bridge.v0.models.SnsNotification, requestHeaders: Seq[(String, String)] = Nil ): F[String] = { val urlPath = Seq("hipchat", "room", roomId, "notification") val (payload, formPayload) = (Some(snsNotification), None) _executeRequest[com.teambytes.hipchat.sns.bridge.v0.models.SnsNotification, String]("POST", path = urlPath, body = payload, formBody = formPayload, requestHeaders = requestHeaders) { case r if r.status.code == 200 => _root_.com.teambytes.hipchat.sns.bridge.v0.Client.parseJson[F, String]("String", r) case r => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Unsupported response code[${r.status.code}]. Expected: 200")) } } } private lazy val defaultApiHeaders = Seq( ("User-Agent", Constants.UserAgent), ("X-Apidoc-Version", Constants.Version), ("X-Apidoc-Version-Major", Constants.VersionMajor.toString) ) def apiHeaders: Seq[(String, String)] = defaultApiHeaders def modifyRequest(request: F[org.http4s.Request[F]]): F[org.http4s.Request[F]] = request implicit def circeJsonEncoder[F[_]: Sync, A](implicit encoder: io.circe.Encoder[A]) = org.http4s.circe.jsonEncoderOf[F, A] def _executeRequest[T, U]( method: String, path: Seq[String], queryParameters: Seq[(String, String)] = Nil, requestHeaders: Seq[(String, String)] = Nil, body: Option[T] = None, formBody : Option[org.http4s.UrlForm] = None )(handler: org.http4s.Response[F] => F[U] )(implicit encoder: io.circe.Encoder[T]): F[U] = { import org.http4s.QueryParamEncoder._ val m = org.http4s.Method.fromString(method) match { case Right(m) => m case Left(e) => sys.error(e.toString) } val headers = org.http4s.Headers(( apiHeaders ++ defaultHeaders ++ requestHeaders ).groupBy(_._1).map { case (k, l) => org.http4s.Header(k, l.last._2) }.toList) val queryMap = queryParameters.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) } val uri = path.foldLeft(baseUrl){ case (uri, segment) => uri / segment }.setQueryParams(queryMap) val request = org.http4s.Request[F](method = m, uri = uri, headers = headers) val reqAndMaybeAuth = auth.fold(request) { case Authorization.Basic(username, passwordOpt) => { val userpass = s"$username:${passwordOpt.getOrElse("")}" val token = java.util.Base64.getEncoder.encodeToString(userpass.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1)) request.putHeaders(org.http4s.Header("Authorization", s"Basic $token")) } case a => sys.error("Invalid authorization scheme[" + a.getClass + "]") } val reqAndMaybeAuthAndBody = if (formBody.nonEmpty) formBody.fold(Sync[F].pure(reqAndMaybeAuth))(reqAndMaybeAuth.withBody) else body.fold(Sync[F].pure(reqAndMaybeAuth))(reqAndMaybeAuth.withBody) httpClient.fetch(modifyRequest(reqAndMaybeAuthAndBody))(handler) } } object Client { import cats.effect._ implicit def circeJsonDecoder[F[_]: Sync, A](implicit decoder: io.circe.Decoder[A]) = org.http4s.circe.jsonOf[F, A] def parseJson[F[_]: Sync, T]( className: String, r: org.http4s.Response[F] )(implicit decoder: io.circe.Decoder[T]): F[T] = r.attemptAs[T].value.flatMap { case Right(value) => Sync[F].pure(value) case Left(error) => Sync[F].raiseError(new com.teambytes.hipchat.sns.bridge.v0.errors.FailedRequest(r.status.code, s"Invalid json for class[" + className + "]", None, error)) } } sealed trait Authorization extends _root_.scala.Product with _root_.scala.Serializable object Authorization { final case class Basic(username: String, password: Option[String] = None) extends Authorization } package interfaces { trait Client[F[_]] { def baseUrl: org.http4s.Uri def hipchatCapabilitiesDescriptors: com.teambytes.hipchat.sns.bridge.v0.HipchatCapabilitiesDescriptors[F] def hipchatInstallData: com.teambytes.hipchat.sns.bridge.v0.HipchatInstallData[F] def serviceInfo: com.teambytes.hipchat.sns.bridge.v0.ServiceInfo[F] def snsNotifications: com.teambytes.hipchat.sns.bridge.v0.SnsNotifications[F] } } trait HipchatCapabilitiesDescriptors[F[_]] { /** * @param redirectToHipchatInstall Whether to redirect to Hipchat install with Base64 encoded data. */ def get( redirectToHipchatInstall: Boolean = false, requestHeaders: Seq[(String, String)] = Nil ): F[com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor] } trait HipchatInstallData[F[_]] { def get( installableUrl: String, redirectUrl: String, requestHeaders: Seq[(String, String)] = Nil ): F[com.teambytes.hipchat.sns.bridge.v0.models.HipchatCapabilitiesDescriptor] def post( hipchatInstallData: com.teambytes.hipchat.sns.bridge.v0.models.HipchatInstallData, requestHeaders: Seq[(String, String)] = Nil ): F[Unit] def deleteByOauthId( oauthId: String, requestHeaders: Seq[(String, String)] = Nil ): F[Unit] } trait ServiceInfo[F[_]] { def get( requestHeaders: Seq[(String, String)] = Nil ): F[com.teambytes.hipchat.sns.bridge.v0.models.ServiceInfo] } trait SnsNotifications[F[_]] { def post( roomId: String, snsNotification: com.teambytes.hipchat.sns.bridge.v0.models.SnsNotification, requestHeaders: Seq[(String, String)] = Nil ): F[String] } package errors { final case class FailedRequest(responseCode: Int, message: String, requestUri: Option[_root_.java.net.URI] = None, parent: Exception = null) extends _root_.java.lang.Exception(s"HTTP $responseCode: $message", parent) } }