crispymtn / crispyfi

Makes music. Loud. https://www.crispymtn.com/stories/let-the-music-play
125 stars 17 forks source link

Writing plugins #13

Open pezholio opened 9 years ago

pezholio commented 9 years ago

Hi,

I'm trying to write a plugin for Crispyfi, and I'm having a little trouble getting my head around node.js's asychronous operations. I want the handle to respond to a search request and give a list of potential matches with a Spotify link. Here's what I've got so far:

class SpotifySearch
  constructor: () ->
    @name = 'Search'
    @response = null

  search: (handler, request, callback) ->
    search = new handler.spotify.Search(request)
    search.execute (err, searchResult) ->
      @str = ""
      for track in searchResult.tracks
        do ->
          @str += "#{track.name} - #{track.link}\n"
      callback @str

  handle: (auth, handler, volume) ->
    if auth.command == "search"
      this.search handler, auth.args.join(" "), (response) ->
        @response = response
    else
      return false

module.exports = () ->
  return new SpotifySearch()

I've tried to use callbacks in the traditional node.js way, but the handler returns before the search completes (because asynchronous). Is there any way I can stop the handler returning until the search has returned? I've tried using promises, but am a bit over my head to be honest! Is there anything easy I'm missing?

dkoch commented 9 years ago

Hey,

off the top of my head, I don't think this is possible using the plugin system, as plugins currently have no way to delay a response.

In a very early version we had a SearchHandler as well, if I remember correctly it was integrated directly into SlackInterfaceRequestHandler. I think we used a flag to indicate whether the response should be returned immediately (for regular commands) or whether control over the response should be handed over to the search handler. While not a beautiful solution, it worked well enough.

Ideally, the whole command handling system would be promise-based so plugins can do whatever they want and the response being triggered only once everything is done.

So, long story short: I don't think you're missing anything. You very likely need to modify SlackInterfaceRequestHandler to listen for your command, then tell it not to send a response immediately, then do your search (while keeping a reference to the response-object) and send the response yourself later on once the search has returned. Sorry for the hassle :/