All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.malliina.push.wns.WNSClient.scala Maven / Gradle / Ivy

There is a newer version: 1.24.4
Show newest version
package com.malliina.push.wns

import com.malliina.http._
import com.malliina.push.Headers._
import com.malliina.push.OAuthKeys._
import com.malliina.push._
import com.malliina.push.wns.WNSClient._
import okhttp3.RequestBody
import play.api.libs.json.Reads

import scala.concurrent.Future
import scala.util.{Failure, Success, Try}

object WNSClient {
  val NotificationHost = "notify.windows.com"

  val CachePolicy = "X-WNS-Cache-Policy"
  val Group = "X-WNS-Group"
  val Match = "X-WNS-Match"
  val RequestStatus = "X-WNS-RequestForStatus"
  val SuppressPopup = "X-WNS-SuppressPopup"
  val Tag = "X-WNS-Tag"
  val Ttl = "X-WNS-TTL"
  val WnsType = "X-WNS-Type"
}

class WNSClient(creds: WNSCredentials) extends PushClient[WNSToken, WNSMessage, WNSResponse] {

  case class PushMeta(client: OkClient, payload: String, headers: Map[String, String])

  def push(token: WNSToken, message: WNSMessage): Future[WNSResponse] =
    withUrls(message) { meta => pushSingle(meta.client, token, meta.payload, meta.headers) }

  override def pushAll(urls: Seq[WNSToken], message: WNSMessage): Future[Seq[WNSResponse]] =
    withUrls(message) { meta =>
      Future.traverse(urls) { url => pushSingle(meta.client, url, meta.payload, meta.headers) }
    }

  private def withUrls[T](message: WNSMessage)(code: PushMeta => Future[T]): Future[T] =
    AsyncHttp.usingAsync(OkClient.default) { client =>
      fetchAccessToken(client) flatMap { accessToken =>
        val contentType = if (message.notification.isRaw) OctetStream else TextHtml
        val allHeaders = message.headers ++ Map(
          Authorization -> s"Bearer ${accessToken.access_token}",
          ContentType -> contentType,
          RequestStatus -> "true"
        )
        code(PushMeta(client, message.payload, allHeaders))
      }
    }

  def pushSingle(
    client: OkClient,
    token: WNSToken,
    body: String,
    headers: Map[String, String]
  ): Future[WNSResponse] = {
    val requestBody = RequestBody.create(body, XmlMediaType)
    client
      .post(FullUrl.build(token.token).toOption.get, requestBody, headers)
      .map(WNSResponse.fromResponse)
  }

  def fetchAccessToken(client: OkClient): Future[WNSAccessToken] = {
    val parameters = Map(
      GrantType -> ClientCredentials,
      ClientId -> creds.packageSID,
      ClientSecret -> creds.clientSecret,
      Scope -> NotificationHost
    )
    val response = client.postForm(
      FullUrl.https("login.live.com", "/accesstoken.srf"),
      Map(ContentType -> FormType),
      parameters
    )
    response.flatMap(r => Future.fromTry(parseResponse[WNSAccessToken](r)))
  }

  def parseResponse[T: Reads](response: HttpResponse): Try[T] = {
    if (response.code == 200) {
      response
        .parse[T]
        .fold(
          invalid => Failure(new JsonException(response.asString, invalid)),
          valid => Success(valid)
        )
    } else {
      Failure(new com.malliina.push.ResponseException(response))
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy