Function within a loop - coffeescript

I'm trying to write a script for hubot to get player statistics for a game, however I am having some trouble with list comprehension.
Here's my code
listings = []
listings =
(for player in players
request "http://pwa.wp3.pl/curvefever/?player=" + player , (err, res, body)->
$ = cheerio.load(body)
msg.send "Hello, world!1"
{name: $('b').slice(0).eq(0).text().toLowerCase(), rank: parseInt($('td').slice(37).eq(0).text(),10)})
msg.send "Hello, world!2"
for player of listings
msg.send "Hello, world!3"
msg.send player.name + " " + player.rank
when running this I get "Hello, world!2" followed by several "Hello, world!1" and no "Hello, world!3" as listings is (presumably) empty.
The script works when I do msg.send instead of trying to capture the listings in an array, however I'd like to sort the listings based on rank too.

Several things are going in here.
First, you do not need to initialize listings as an array first.
Second, I think you're looking for for player in listings.
Third, and I think that's the most important point :
request sends an ajax request. Ajax requests are, by definition, asynchronous.
So what you actually push into your array is the result of "request" : probably nothing.
I'd recommend using a library such as async.js, a promise implementation, etc, or just a i = players.length that you decrement and check each time a request succeeds, to ensure your code awaits all results before it executes.

Related

Is there a way to make Hubot reply to all messages that are not existing commands?

I'm giving Hubot a first try, and I'm making a dialog script for basic conversation. I have completed quite a few possibilities (I have a lot of questions and keywords working,) but when the user asks or says something Hubot doesn't recognize, it's complete silence.
I want to add a default set of answers for Hubot when it can't find an existing command or words (vague replies like "That's interesting" or "Tell me more".)
Is there a way to do this via script? Something like:
robot.respond / * /, (msg) ->
msg.send ArrayOfVagueReplies
where * is "everything else". "If commands... else..."?
use robot.catchAll clause to catch all non-matched dialogues, you can reference to https://www.npmjs.com/package/hubot-suggest
Since hubot's robot.respond method takes a regex, you should be able to just supply /.*/ as the regex, and have it match everything.
So you'd have:
module.exports = (robot) ->
robot.respond /.*/i, (msg) ->
doSomething(msg)

Make Hubot run preconfigured commands automatically

I'm using Hubot on flowdock and I'm trying to make Hubot post automatically the respond of a user command.
With the help of https://leanpub.com/automation-and-monitoring-with-hubot/read#leanpub-auto-periodic-task-execution , I've managed to make Hubot talk at a specific time creating a cron.coffee script, so no issues with that.
The thing is that I have another script (trello.coffee) that makes Hubot respond to the command "show cards" and I want the result of this command to be posted in a specific time without the need of me telling Hubot to do this.
How exactly can I do this without the need to write another script (ie. trello.auto.coffee) and the whole robot.emit -> robot.on procedure?
What about using the http listener?
This page has a section for HTTP Listener and has this code example:
module.exports = (robot) ->
robot.router.post '/hubot/chatsecrets/:room', (req, res) ->
room = req.params.room
data = if req.body.payload? then JSON.parse req.body.payload else req.body
secret = data.secret
robot.messageRoom room, "I have a secret: #{secret}"
res.send 'OK'
Would that work?

Claiming a Ticket in RT via REST

I'm currently working on using Javascript to make REST calls to our Request Tracker system. The Javascript hasn't been a problem so far, but the documentation for RT+REST is just a little bit sparse. The goal is to claim a ticket. I've tried sending (POST):
REST/1.0/ticket/$num/take
And I get an error about not having a required parameter 'changes'
Then, I tried this:
REST/1.0/ticket/$num/take
id: $num
action: take
And I get the same error message. The last thing I've tried was:
REST/1.0/ticket/742685/edit
id: $num
action: take
And the response was "RT/ver 200 Ok" with all of the ticket information, but it didn't actually transfer ownership.
What am I missing?
On the off chance that someone else can use this, I think most of the RT REST/v1 endpoints require that all of the "key: value" strings be wrapped under a "content" key in the request payload. I also didn't see anything about a /take endpiont, so I might try something like:
var endpoint = base + 'REST/1.0/ticket/742685/edit'
var payload = {'content' : "id: 742685\n Owner: Some New Owner"}
makePost(endpoint, payload)
Worth a shot.

How do I use send/topic from within a robot.router.post block in hubot

I've been hacking away with hubot for a few weeks now and loving it but have been stuck for a couple of days on the code snippet below. I have a listener that is receiving events via webhooks from our ticket system. That's working great! The problem I'm having is how do I then send some of this data to a room and update the topic?
Normally this is done via the msg.send or msg.topic callback that is sent with functions such as robot.respond but when using robot.router.post, I'm not clear on what object I should be referencing to send the message. Basically, how/where do I get msg defined within robot.router.post?
Apologies for newbness, I'm pretty new to all things javascript/coffeescript. Thanks!
module.exports = (robot) ->
robot.router.post "/hubot/ticket_change", (req, res) ->
ticket_info = req.body.issue.name + ": " + req.body.issue.summary
robot.send ticket_info
robot.topic ticket_info
room = <room id>
robot.messageRoom room, ticket_info

Why is the loop portion of this loop react block not "looping" the way I expect?

I'm working on a homework assignment, modifying code created by my professor. Unfortunately, he's not available to me currently so I'm reaching out to the stackoverflow crowd.
This snippet is from a file "Peer.scala", which communicates with an actor from another class "RemoteActorChat.scala". I have only included the snippet that I believe is the cause of my issue, for the sake of brevity. Should the rest of the code be useful in finding a solution, I'll gladly post it.
My intent is to have the Peer capture input from the console in a continuous loop, while simultaneously reacting to any messages received from the RemoteChatActor.
...
def act {
...
loop {
val textInput = Console.readLine(name + ">").toString()
textInput match {
case "Unsubscribe" =>
unsubscribe
case "Subscribe" =>
subscribe(name))
case "?" =>
println("Type any message to send it to the chatroom")
println("Type 'Unsubscribe' (without quotes) to leave the chatroom")
println("Type 'Subscribe' (without quotes) to re-join the chatroom")
case _ =>
post(textInput)
}
react {
case Post(msg) =>
println(name + " got a post = " + msg)
}
}
}
...
When the inputText is matched to _ the post function is called, does it's thing and I get another prompt. I can post messages all day long like this if I want.
However, when inputText is matched to "Unsubscribe", "Subscribe", or "?", the behavior is different. The statements in the case are executed IE) the unsubscribe or subscribe functions are called and do their thing as expected. However, I don't get the prompt back to continue sending input from the console. The peer basically just hangs at this point. I expect another prompt but the console window is just empty and doesn't take any additional input.
Clearly my understanding of how this should work is flawed.
What am I misunderstanding, and how can I make this do what I intend?
The actor is waiting for a Post inside react. It won't continue until it gets one. Since you only send one in one case, only that case gets through.
If you want to make the other cases work, either have them also send a message that the react block can receive (at least as a case _ inside the react block), or move the react block so it will only be entered if there will in fact be a Post coming back its way at some point.