dont want to notify all members in play framework socket chat - sockets

i am tottaly new in play framework web socket.
i downloaded a application of chat from the https://github.com/playframework/playframework/tree/master/samples/scala/websocket-chat
and i am learning it for the notifications in project. but the problem is that i am not understading the behaviour of the code. like in below code, i want to set the members whom twill recived the msg.
previusly members contatining all username of users that are in chat room, i modify it and set it to only one user "govind" but still all members are notifing,
simply i want to notify only some users
def notifyAll(kind: String, user: String, text: String) {
members=Set.empty[String]+"govind"
val msg = JsObject(
Seq(
"kind" -> JsString(kind),
"user" -> JsString(user),
"message" -> JsString(text),
"members" -> JsArray(
members.toList.map(JsString)
)
)
)
chatChannel.push(msg)
}
and what it does
sender ! Connected(chatEnumerator)
self ! NotifyJoin(username)

Take a look at the play.api.libs.iteratee.Concurrent to find other options than broadcast (one to many). You probably want to read up on both iteratees and actors to see what fits your use case best.
James Roper wrote a nice blog article about iteratees that you can find here:
http://jazzy.id.au/default/2012/11/06/iteratees_for_imperative_programmers.html
The Akka docs are good for getting into how and what Actors are:
http://doc.akka.io/docs/akka/2.3.1/intro/what-is-akka.html
Also, if you are new to Play then you should probably invest some time in getting a firm grip on the basic before jumping into more advanced stuff like iteratees.

Related

Google action builder/Google assitant How to use proper noun as type

i would like to have a type that represent proper nom, such as family name for exemple but i can't find anything on this.
My goal is to send a info to an other personne using google assistant and my backend.
For exemple the user can say "Send this info to john smith" the info is stored in my backend so i have no problem finding and i got the id of the personne who is talking to the google assistant so this is no problem either.
The problem is how can i get john smith as a parameter that i send to my webhook? So my backend can verify the user list in my database and send the info if the user existe. I tried to use Type but a family doesn't match any pattern because it's can be anything...
If anyone know how to use google action builder with proper noun i would be grateful to know how i can manage to do it.
You have generally two options.
Free form text approach
First you can create a "Free form text" type which can catch pretty much anything being said.
Then a custom intent can be trained with a few examples to pull out the correct proper noun (or anything else). Your webhook will be able to match at that point.
Type Overrides approach
Alternatively, you can create a new type that starts with a preset of sample names that you use in your custom intent. Then, when the action starts, you can get the user's personal contact list in the webhook and set session type overrides.
Here's an example of the code I got from a music player action:
conv.session.typeOverrides = [{
name: 'genre',
mode: Mode.TypeReplace,
synonym: {
entries: Array.from(trackGenres).map(genre => ({
name: genre,
synonyms: [genre]
}))
}
}]
Depending on your system architecture, one of these may make more sense than the other. The first is better at capturing everything, but may require more post-processing on your webhook. The latter is better at precision, but may mean names may not match if they don't match entirely.

Formulate correct scenario phrase

I would like to know, if the following Gherkin phrase correspond to BDD rules:
final class KafkaSpec extends BddSpec {
feature("Kafka distribution to SAP server via websocket") {
scenario("Kafka consumer does not receive messages from Kafka server") {
Given("Kafka server is NOT active")
When("consumer client get started")
val ex = SenderActor.run
Then("print message `Failed to connect to Kafka`")
ex.failed map { ex =>
assertThrows[ConnectException](ex)
}
}
scenario("Kafka consumer receives messages from Kafka server") {
Given("Kafka server is ACTIVE")
When("consumer client get started")
Then("print message `Successfully connected to Kafka`")
succeed
}
}
}
Do I use the right tense? Do I use the Given-When-Then correctly?
The Givens (contexts) are fine; we normally use either continuous present or past tense for those:
Given the kafka server is active <-- continuous present
Given the kafka server was started <-- past tense
For the Whens (events), it's better if you can use an active voice. Active voice starts with who did it. Who started the server? (I've corrected the English a bit here too.)
When the consumer client was started <-- passive voice
When our consumer starts their client <-- active voice
For the Thens (outcomes), I really like the word "should". It encourages people to question it; should it really happen? Now? In this release? Is there any context for which this shouldn't happen or something different should happen? Should it still happen, or has this scenario changed?
Then the consumer interface should print the message, `Successfully connected to Kafka`.
One other thing though: the detail in that last step feels a bit too much to me. If the message changed, you'd have to change it everywhere. Instead I keep that in the code (you can abstract the step out) and would say something like:
Then the interface should tell the consumer that the connection was successful.
This is something we usually call "declarative over imperative". It's also OK to have the passive voice here:
Then the consumer should be told that the connection was successful.
Using the word "should" also helps differentiate between the outcomes of one scenario and the givens of another; often these overlap with an outcome forming the context for another scenario:
Given Priscilla has an account
When she enters her username and password correctly
Then she should be on her home page.
Given Priscilla is on her home page...
I wrote more about tenses and language of BDD here, where you'll also find tons of other resources for new BDDers under the BDD category.

Hubot Message Only Specific Channel On Enter/Leave

Working on creating a list of messages that Hubot can randomly choose from to display in the #general channel when someone joins the company. I've got the message part working, but it's doing it on ANY channel... how can I limit it to just a specific channel? One step further, would like to take the users name who entered and paste it inside the sentences if possible.
Thanks!
validWelcome = [
'We have a new kid on the block, Hello!'
'Welcome the newest member to the team!'
'Thanks for joining us!'
'Happy to have you here!'
]
module.exports = (robot) ->
robot.enter (msg) ->
msg.send {room: '#integration-test'}, msg.random validWelcome
There are two issues to consider
Does the chat software you are using expose enough information to Hubot via the adapter when a user joins a room (see docs)
Do you want to display this message if someone leaves and re-joins the #general room?
Taking a wild guess that you are using Slack you can see what the Slack adaptor sends you here. You really want access to channel.name but you can get channel.id from msg.room and take it from there and solve #1. If you're not using Slack find the source for your adapter and search for EnterMessage.
If you want to solve #2 you'll need to do something clever with Hubot's brain and record the fact that you've sent a welcome for each user.

Playframework User Actor with User Session

I'm pretty new to Scala, the Play Framework and Akka. In the project I currently work on, the user of the web application should be able to ask the server several things to do (like starting a particular computation) in an asynchronous way. If the server is done it should notify the user also async. I solve this demand by a WebSocket connection which is established when the user first connects with the Application and the WebSocket is handled by a UserActor, which is attached to the User Session:
def ws = WebSocket.tryAcceptWithActor[JsValue, JsValue] { implicit request =>
Future.successful(request.session.get(UID) match {
case None => Left(Forbidden)
case Some(uid) => Logger.info("WebSocket has accepted the request with uid " + uid)
Right(UserActor.props(uid))
})
}
Currently, the only thing the UserActor does is receiving messages from the WebSocket as JsValue. The UID of the session is generated when requesting index:
def index = Action { implicit request => {
val uid = request.session.get(UID).getOrElse {
counter += 1
counter.toString
}
Ok(views.html.index(uid)).withSession {
Logger.debug("create uid " + uid)
request.session + (UID -> uid)
}}
}
The UserActor should represent the actual user on the Server and thus include the logic of all actions that the user can perform on the Server. This works fine as long as I send all user interaction over the WebSocket.
Now what is the case with other user input, like form submission? The application includes a form whose data should not go over the WebSocket, but rather be submitted with a POST request (perhaps with AJAX) and bound in a controller to the Model like described in the documentation.
def saveContact = Action { implicit request =>
contactForm.bindFromRequest.fold(
formWithErrors => {
BadRequest(views.html.contact.form(formWithErrors))
},
contact => {
val contactId = Contact.save(contact)
Redirect(routes.Application.showContact(contactId)).flashing("success" -> "Contact saved!")
}
)
}
This example is taken from the Playframework documentation.
Now, how do I link the Form Submission handler with the UserActor? Say I want to tell the user actor that a form has been submitted. A trivial example would be that the UserActor sends one value of the form back over the WebSocket to the client as soon it is received. So basically the problem reduces to the issue that I want to send the UserActor Messages from any Controller.
I might come up with the idea to send all form data over the WebSocket, but I also want to realize the upload of large data in the future, which I want to tackle like described in this blog post. Then one scenario I could imagine is that the UserActor should be messaged for each chunk it receives.
I guess one problem is that the UserActor and the WebSocketActor are the same and I rather should split their logic, such that the UserActor is only associated with the Session, but I have no idea how to accomplish this. Maybe I need another actor, say a UserManager, which keeps track of present UserActors and enables access to UserActors?
Do you have any suggestions, recommendations or perhaps an example application which also deals with this case? Thank you very much in advance.
Best regards
Don't use the actor that you pass to tryAcceptWithActor as a representation of the User. It should represent a particular session with that user. Possibly, one of many concurrent sessions (multiple browsers, or tabs) a user could have open at a particular time.
Create a separate actor to represent the user and all of the actions it can perform. Now the session actors should forward their messages to the user actor. Traditional controller methods can also forward requests to the corresponding user actors.

Close twitter streaming connection in play framework

I connect to twitter streaming API using Play 2.2 WS API in the code example below. I'm stuck trying to figure out how to disconnect from stream once it's established. Is there any proper way to do that rather than stopping application? Any help will be appreciated.
def watchTweets(keywords : String) = Action { implicit request =>
Logger.debug(s"watchTweets invoked with: $keywords")
val (tweetsOut, tweetChanel) = Concurrent.broadcast[JsValue]
WS.url(s"https://stream.twitter.com/1.1/statuses/filter.json?track=" + URLEncoder.encode(keywords, "UTF-8"))
.sign(OAuthCalculator(Twitter.KEY, Twitter.sessionTokenPair.get))
.postAndRetrieveStream("")(headers => Iteratee.foreach[Array[Byte]] { ba =>
val msg = new String(ba, "UTF-8")
Logger.debug(s"received message: $msg")
val tweet = Json.parse(msg)
tweetChanel.push(tweet)
}).flatMap(_.run)
Ok.chunked(tweetsOut &> Comet(callback = "parent.cometMessage")) }
This is a known issue... the answer is that you close the connection, but the problem is, the enumerator won't notice that the connection is closed until it tries to feed a tweet to the client, and that won't happen until it receives another tweet from Twitter, which might take a long time to happen.
This is of course a problem when doing Twitter streaming because Twitter will only let a user create one stream at a time, so that effectively means that you can't do a second stream until the first receives some data.
Unfortunately we don't have a work around as yet, but we are looking at introducing a new lower level streaming API into Play around the 2.4 time line, which will certainly allow this.