Search code examples
pythonpython-3.xerrbotchatops

Personalizing API calls in Errbot / How to store and access user specific information in Errbot?


What is the best way to store and access user specific information in Errbot that is accessible to all plugins?

My use case is creation of a Redmine (issue tracking) plugin that allows users to create, update, close, assign issues etc.

This is gettable via a single user token, but this not feasible as all issues will be authored, updated, time logged by the same user.

Can someone suggest me a way so that users can store and update their user tokens and the plugin fetches the same and uses it to call apis?

P.S. I'm just introduced to Chatops/Errbot and trying out stuff. Please let me know if there is a better approach.


Solution

  • You ask about storing information that is accessible to all plugins. That can be achieved with plugin dependencies but actually doesn't seem applicable to your use-case because you only appear to need those user tokens to redmine in your redmine plugin, not any other plugins.

    Can someone suggest me a way so that users can store and update their user tokens and the plugin fetches the same and uses it to call apis?

    First off, it depends on how your plugin needs to authenticate itself to Redmine. Based on your question I'm assuming Redmine just offers an API key in a users profile setting that you need to store and use so I'll go with that, but it gets more complicated if the method of obtaining said token is more involved.

    So assuming a user can get his API token from his profile and just needs to let the bot use it, you can:

    1. Provide a command for users to set their API token, storing it using the builtin persistence:

      def activate(self):
          super().activate()
          if 'tokens' not in self:
              self['tokens'] = {}
      
      @botcmd
      def set_redmine_token(self, msg, args):
          # See http://errbot.io/en/latest/user_guide/plugin_development/persistence.html#caveats
          # for an explanation of the mutable thing.
          with self.mutable('tokens') as tokens:
              tokens[msg.frm.person] = args
          return "API token set"
      
    2. When making API calls to redmine, you can then see if you have a token on file for the user issuing the command and use that, display an error otherwise:

      @botcmd
      def do_redmine_thing(self, msg, args):
          if msg.frm.person not in self['tokens']:
              return "I don't have a token for you, please set it with !set_redmine_token <token>"
      
          # Now do your API thing, using the token from
          # self['tokens'][msg.frm.person]
      

    Note that the above is a really bare-bones example. You'll probably want to use arg_botcmd over plain botcmd for better argument parsing, do more error checking, etc.