-
-
Save inanna-malick/f3be49262e28aba31cf5 to your computer and use it in GitHub Desktop.
Using Pusher API with Play framework in scala for publishing events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//send messages via Pusher API in play 2.4 | |
import play.api.libs.json.{ Writes, Json } | |
import play.api.libs.ws.{ WSResponse, WSClient } | |
import play.api.libs.ws.ning.NingWSClient | |
import java.security.MessageDigest | |
import java.math.BigInteger | |
import javax.crypto.Mac | |
import javax.crypto.spec.SecretKeySpec | |
import scala.concurrent.{ ExecutionContext, Future } | |
object Pusher { | |
val appId = "app_id" | |
val key = "key" | |
val secret = "secret" | |
val domain = "api.pusherapp.com" | |
val client = NingWSClient() | |
val p = new Pusher(client, PusherConfig(appId, key, secret, domain)) | |
case class Msg(foo: String, bar: String) extends PusherEvent { | |
val eventName = "test event with type msg" | |
} | |
implicit val ec = scala.concurrent.ExecutionContext.Implicits.global | |
implicit val writes = Json.writes[Msg] | |
def trigger() = p.trigger("test_channel", Msg("hello", "world")).onSuccess { | |
case resp => | |
println(resp) | |
println(resp.body) | |
} | |
} | |
case class PusherConfig(appId: String, apiKey: String, secret: String, domain: String) | |
trait PusherEvent { | |
val eventName: String | |
} | |
class Pusher(client: WSClient, pusherConfig: PusherConfig) { | |
import pusherConfig.{ appId, apiKey, secret, domain } | |
//current timestamp in seconds, used for pusher auth | |
def authTimestamp() = System.currentTimeMillis() / 1000 | |
//create and send a signed request: https://pusher.com/docs/rest_api#auth-signature | |
def trigger[T <: PusherEvent](channel: String, message: T)(implicit writes: Writes[T], ec: ExecutionContext): Future[WSResponse] = { | |
val url = "/apps/"+appId+"/channels/"+channel+"/events" | |
val body = Json.toJson(message).toString() | |
// request signature component: query parameters sorted by key, with keys converted to lowercase, | |
// then joined as in the query string. Note that the string must not be url escaped | |
// (e.g. given the keys auth_key: foo, Name: Something else, you get auth_key=foo&name=Something else) | |
val params = List( | |
"auth_key" -> apiKey, | |
"auth_timestamp" -> authTimestamp().toString, | |
"auth_version" -> "1.0", | |
"name" -> message.eventName, | |
"body_md5" -> md5(body) | |
).sortBy { case (key, _) => key } | |
val encodedParams = | |
params.map { case (key, value) => key+"="+value }.mkString("&") | |
val toSign = List("POST", url, encodedParams).mkString("\n") | |
val signature = sha256(toSign, secret) | |
val signedParams = params ++ List("auth_signature" -> signature) | |
client.url("http://"+domain + url).withQueryString(signedParams: _*).post(body) | |
} | |
private[this] def byteArrayToString(data: Array[Byte]): String = { | |
val hash = new BigInteger(1, data).toString(16) | |
"0" * (32 - hash.length) + hash | |
} | |
private[this] def md5(s: String): String = | |
byteArrayToString(MessageDigest.getInstance("MD5").digest(s.getBytes("US-ASCII"))) | |
private[this] def sha256(s: String, secret: String): String = { | |
val mac = Mac.getInstance("HmacSHA256") | |
mac.init(new SecretKeySpec(secret.getBytes, "HmacSHA256")) | |
val digest = mac.doFinal(s.getBytes) | |
String.format("%0"+(digest.length << 1)+"x", new BigInteger(1, digest)) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<title>Pusher Test</title> | |
<script src="https://js.pusher.com/3.0/pusher.min.js"></script> | |
<script> | |
// Enable pusher logging - don't include this in production | |
Pusher.log = function(message) { | |
if (window.console && window.console.log) { | |
window.console.log(message); | |
} | |
}; | |
var pusher = new Pusher('key', { | |
encrypted: true | |
}); | |
var channel = pusher.subscribe('test_channel'); | |
channel.bind('my_event', function(data) { | |
alert(data.message); | |
}); | |
</script> | |
</head> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment