Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manually call a .respond listener #823

Closed
lukerollans opened this issue Nov 25, 2014 · 8 comments
Closed

Manually call a .respond listener #823

lukerollans opened this issue Nov 25, 2014 · 8 comments

Comments

@lukerollans
Copy link

I'm wondering if there's a best practice way of manually calling a .respond listener. In some instances, it would be great if I could manually call one and let params go through as default (eg, msg.match[1] for example will match nothing and fallback to default).

Normally, the action performed by the listener being called would be abstracted out but I'm just curious if anyone else has gone this way.

For example

module.exports = (robot) ->
  robot.respond /hello!/i, (msg) ->
      msg.send "Hello to you too, sir!"
      # Something here to call the below listener and have Hubot also wish the user a great day

  robot.respond /have a great day/i, (msg) ->
      msg.send "I wish upon you a fantastic day, as well!"
@technicalpickles
Copy link
Member

For your own scripts, I've found it most useful to have functions that multiple listeners can call.

For using other listeners, there's not really a simple way of getting listeners and calling them. That said, you can probably experiment a bit to find a way. Here's some pointers:

So basically, you might be able to loop over robot.listeners to get a specific listener. Then, construct a Message object and then call into it. There is some confusing bit about hubot, where the msg object in your example is actually a Response object, but msg.message is a Message object. You'd be able to massage the Message object of the current response before calling the other listener. But note, if it doesn't match the regex, it wouldn't actually get called.

Kinda related is #803 which would add support to listeners to have metadata, which would make it easier to identify in the array.

@lukerollans
Copy link
Author

Thanks for the input 👍

I agree, the most useful and best practice way would be to abstract out the deeper stuff. As you said, have functions that multiple listeners can call.

@michaelansel
Copy link
Collaborator

As soon as #803 merges, I've got a commit queued up to add robot.listenerById which will retrieve a specific listener based on its ID (a new metadata field introduced in #803). You would then be able to execute the listener directly using the private API call.

In a unit test scenario:

  describe 'listener "get-room-oncall"', ->
    it 'should match "who is oncall?"', (testDone) ->
      listener = @robot.listenerById 'get-room-oncall'

      # Stub out the real work; just testing the match
      listener.callback = sinon.stub() # private API

      testMessage = new TextMessage @user, "TestHubot: who is oncall?"

      listener.call testMessage, (result) -> # private API
        expect(result).to.be.ok
        testDone()

The relevant bit of script would be:

module.exports = (robot) ->
  robot.respond /who is oncall?/, id: 'get-room-oncall', (response) ->
    # it does stuff

@dgershman
Copy link

i'm interested in being able to do this too, it seems kind of odd that I can't arbitrarily send a message back to hubot and chain event togethers.

@michaelansel
Copy link
Collaborator

@radius314 What exactly are you trying to accomplish? While I hope to enable listener retrieval soon, I envision manual invocation as an edge case (call is a private API). Most reuse of logic should be done with functions, external modules, and events.

@michaelansel
Copy link
Collaborator

Opened #1031 to add robot.listenerById. When that merges, I'll close this.

@stale stale bot added the stale label May 30, 2017
@stale
Copy link

stale bot commented May 30, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot closed this as completed Jun 8, 2017
@xrysanthos
Copy link

xrysanthos commented Sep 28, 2017

Hi all! This type of functionality is really important when it comes down to re-using behind the scenes 3rd party script packs. For example if I'm building a script pack for my specific business context it would be great if I could just execute one or more commands exposed by another library (e.g. google maps scripts, etc) explicitly by using its text patterns.

This way developers can really work on the semantic layer of things without having to worry about internal listener IDs and other low-level stuff. @michaelansel solution is clean but cannot work with existing libraries if no IDs have been specified for each listener.

For example if my listener hears for:

get service x location

and I'm using hubot_maps as a dependency, my service would return the location details in the controller and if I wanted to enrich the message with geo info I'd just have an extra step calling

hubot map me 'query'

passing the coordinates, get its response and return the enriched message.

Command composition is definitely a great way of leveraging re-usability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants