Code Monkey home page Code Monkey logo

hippybot's Introduction

Introduction

HippyBot is a Hipchat.com chatroom bot written in Python. It is technically just a Jabber/XMPP bot, but it has customised features for connecting to and working on Hipchat.

HippyBot includes a simple plugin API for adding commands.

Installation

There a few ways you can install Hippybot:

Download and install with setup.py:

python setup.py install

Install from PyPi:

pip install hippybot
# or using setuptools
easy_install hippybot

Configuration

There is an example configuration file distributed with HippyBot called hippybot.conf.example, copy this and edit it. You will need to add an account to your Hipchat group for the bot to connect as. While logged in as the account go to the XMPP settings page to get the details you'll need to edit the config file.

Usage

Run HippyBot from a terminal like so:

hippybot -c path/to/your/config/file.conf

To run as a background daemon use -d or -daemon:

hippybot -c path/to/your/config/file.conf -d

Optionally you can provide a path to a PID file to use with -p or --pid. Note: at present you will have to provide your own control script, e.g. for use with init.d or upstart.

You should see the bot join any channels listed in the config file. You can then target the bot with commands using the at-sign notation, e.g.:

@botname rot13 hello world

If you have the rot13 example plugin set to load (via the plugins section of the config file) then the bot will reply to you using at-sign notation with a ROT13'd (each character offset by 13) version of the text "hello world".

The bot has 2 inbuilt commands:

  • load_plugins: this will reload any updated plugins (note it will also reset the internal state of any loaded plugins, e.g. the counter in the mexican wave plugin). Note it does not reload the bot's configuration file and so will not load new plugins.
  • reload: this will reload the bot itself, reloading the configuration file, reconnecting to HipChat and reloading any plugins, in the process. Note: it does not end the main process, you would have to do that yourself from the terminal (for example if HippyBot were updated).

Plugins

There are 3 plugins currently distributed with HippyBot:

  • rot13: this is mostly included as an example, it ROT13s, any text spoken directly to the bot, back at the speaker.

  • mexican_wave: this is a fun plugin that completes a mexican wave if 2 people in a row say \o/ in a channel, e.g.:

    John Smith: \o/
    Joe Bloggs: \o/
    Hippy Bot:  \o/
    
  • udefine: look up a term on Urban Dictionary, the first 3 definitions will be posted back to the channel. Warning: many terms are NSFW.

To instruct the bot to load a plugin include the plugin's module path in the load field of the plugins section of the config file, e.g. to load the mexican_wave plugin which is located in the file mexican_wave.py in hippybot/plugins/, you would write it as:

[plugins]
load = hippybot.plugins.mexican_wave

To load a plugin named my_custom_plugin that you have installed into your python path under myhippybotplugins in a filename (or module) named my_custom_plugin.py you would append (on a new line, notice the indentation):

[plugins]
load = hippybot.plugins.mexican_wave
       myhippybotplugins.my_custom_plugin

To search for plugins in paths outside of hippybot, you can use the load_path option:

[plugins]

load_path = /absolute/path/plugins
    hippybot/plugins
    plugins
    another/relative/path

Plugin API

HippyBot includes a very simple plugin API. To add commands to HippyBot you just need an importable Python package (e.g. a directory in the PYTHON_PATH that includes a file named __init__.py), and place your plugin in it's own Python file (the ROT13 plugin lives in rot13.py).

You then can include a function that matches the same name as the file and is the same command you want to register, and use either the botcmd or directcmd decorators:

# hello_world.py
from hippybot.decorators import directcmd

@directcmd
def hello_world(bot, mess, args):
    return u'Hello world!'

This registers the command hello world as a direct command, that means the text "Hello world!" will be directly spoken back to the user using at-sign notation. The botcmd decorator on the other hand will respond in the channel without targetting the original speaker. By default these function based plugins only support direct commands (spoken to the bot using at-sign notation), however you can create more complex plugins with greater control using class based plugins.

To create class based plugins create the Python module as normal, with any descriptive name you want, and include a class named Plugin in the module, for example the hello world plugin can be written like:

# hello_world.py
from hippybot.decorators import botcmd, directcmd

class Plugin(object):
    global_commands = ['hello_world']
    command_aliases = {'hi!': 'hello'}

    @botcmd
    def hello_world(self, mess, args):
        return u'Hello world!'

    @directcmd
    def hello(self, mess, args):
        return u'Well hello there..'

This uses 2 special properties:

  • global_commands: a list of command method names that can be triggered without targetting the bot using at-sign notation (just say the command in the channel without mentioning the bot).
  • command_aliases: dict of command aliases and the methods they map to, this is a way of triggering a command from a string that can't be used as a Python method name (e.g. using special symbols such as the "o/" trigger used in the mexican wave plugin).
  • all_msg_handlers: a list of handler method names that will be passed all incoming XMPP message objects regardless of type as. This can be used for low-level hanbdling of Jabber messages without using the higher level message handling of jabberbot or hippybot.

HipChat API

HippyBot includes a very simple object orientated wrapper for the HipChat API. To make use of the API you need to create an API key and enter that into the config file under the section hipchat, as an option called api_auth_token, e.g.:

[hipchat]
api_auth_token = xxxxxxxxxxxxxxxxxxxxxxxx

If you are using self-hosted Hipchat service, set up something like this:

[hipchat]
api_server = api.example.com
api_auth_token = xxxxxxxxxxxxxxxxxxxxxxxx

Then you can access the wrapper via the api attribute on the bot instance, e.g. from within a command method on a plugin class:

# hello_world.py
from hippybot.decorators import botcmd

class Plugin(object):
    global_commands = ['hello']

    @botcmd
    def hello(self, mess, args):
        channel = unicode(mess.getFrom()).split('/')[0]
        # Say hello world as a room notification
        # Params to the API wrapper are sent as dicts
        self.bot.api.rooms.message({
            'room_id': channel,
            'from': self.bot._config['connection']['nickname'],
            'message': 'Hello world!'
        })

hippybot's People

Contributors

1stvamp avatar charlax avatar claudyus avatar jzhuge avatar orb avatar veszig avatar zentavr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hippybot's Issues

Plugins not loading: ImportError: No module named hello_world

I am trying to write a plugin for hippybot but i cannot seem to even get the basic hello_world sample plugin loaded.

I created a file hippybot/plugins/hello_world.py and added the content in the README, i then added the line hippybot.plugins.hello_world to the config (corectly indented) and then went to start the bot and it spits out an error from bot.py and lazy_reload.py saying "ImportError: No module named hello_world" i tried writing my own also and i get the same issue, as soon as i remove this plugin from the config and just leave the defaults it works great.

Any ideas?

plusplusbot doesn't handle unicode usernames

User has a unicode character in his username. This results, and hippybot crashes:

ERROR: 'ascii' codec can't encode character u'\xae' in position 34: ordinal not in range(128)
Traceback (most recent call last):
  File "/home/michael/work/hippybot/python/lib/python2.7/site-packages/hippybot-1.2.4-py2.7.egg/hippybot/bot.py", line 291, in run
    bot.serve_forever()
  File "/home/michael/work/hippybot/python/src/jabberbot/jabberbot.py", line 823, in serve_forever
    conn.Process(1)
  File "build/bdist.linux-x86_64/egg/xmpp/dispatcher.py", line 303, in dispatch
    handler['func'](session,stanza)
  File "/home/michael/work/hippybot/python/lib/python2.7/site-packages/hippybot-1.2.4-py2.7.egg/hippybot/bot.py", line 156, in callback_message
    ret = cmd(mess)
  File "/home/michael/work/hippybot/python/lib/python2.7/site-packages/hippybot-1.2.4-py2.7.egg/hippybot/plugins/plusplusbot.py", line 32, in change_score
    room = str(mess.getFrom()).split("/")[0]
UnicodeEncodeError: 'ascii' codec can't encode character u'\xae' in position 34: ordinal not in range(128)

Hippybot not joining rooms/channels

Unsure if this is related, but it's throwing an
"ERROR:jabberbot:item-not-found"
upon start.

I installed via pip install hippybot, but I had to manually install beautifulsoup via pip as well.

I've verified from the XMPP (hipchat.com/account/xmpp) page that the room names are correct. I'm using the XMPP names, but I've also tried the HipChat room names.

What am I doing wrong?

Use mention_name instead of name when sending a direct message

A user can change their HipChat mention name by going into their web settings.

However, the current method of getting the name to send a direct message to is by manipulating the from field in the message:

In https://github.com/1stvamp/hippybot/blob/master/hippybot/decorators.py:

username = unicode(origin.getFrom()).split('/')[1].replace(" ","")

If the user has changed their mention name to something other than the concatenation of their first and last name, then hippybot direct messaging won't work as intended.

Via the HipChat API, it looks like you can pull the user's mention_name:

https://www.hipchat.com/docs/api/method/users/show

If the user has an API token configured, you could pull their mention_name via the HipChat API and then leverage it. Cache it, too, for bonus points!

it looks like you can pull all users at once via the HipChat API, so another way to solve would be to pull the list on bot startup and cache it. It misses some edge cases (new users or users that change their mention_name since the bot started up), but the list could be re-pulled on bot reload.

GET /v1/users/list?format=json&auth_token=token HTTP/1.1
Host: api.hipchat.com

Unfortunately, it looks like the HipChat API token has to be an admin token in order to pull the user list.

Bot hits the 150s timeout while running in foreground

To repro, simply run a bot connected to a room with only 1 human participant. Wait 150seconds.

Traceback (most recent call last):
  File "bot.py", line 210, in <module>
    sys.exit(main())
  File "bot.py", line 200, in main
    bot.serve_forever()
  File "/usr/local/lib/python2.7/dist-packages/jabberbot.py", line 601, in serve_forever
    conn.Process(1)
  File "/usr/lib/python2.7/dist-packages/xmpp/dispatcher.py", line 303, in dispatch
    handler['func'](session,stanza)
  File "/usr/lib/python2.7/dist-packages/xmpp/dispatcher.py", line 215, in streamErrorHandler
    raise exc((name,text))
xmpp.protocol.StreamError: (u'service-unavailable', u'Timed out after 150s of inactivity')```

Hippybot fails to run

I am unable to run Hippybot. I get an import error stating no module named wave.

I am using Python 2.7 on Windows 7 64-bit.

> hippybot.exe -c hippybot.conf

ERROR: No module named wave
Traceback (most recent call last):
  File "C:\Python27\venv\py27-hippybot\lib\site-packages\hippybot\bot.py", line
256, in run
    bot = HippyBot(self.config._sections)
  File "C:\Python27\venv\py27-hippybot\lib\site-packages\hippybot\bot.py", line
69, in __init__
    self.load_plugins()
  File "C:\Python27\venv\py27-hippybot\lib\site-packages\hippybot\bot.py", line
190, in load_plugins
    module = do_import(path)
  File "C:\Python27\venv\py27-hippybot\lib\site-packages\hippybot\bot.py", line
26, in do_import
    mod = __import__(name)
  File "C:\Python27\venv\py27-hippybot\lib\site-packages\lazy_reload.py", line 8
3, in _lazy_reload_import
    m = _real_import(name, globals, locals, fromlist, level)
ImportError: No module named wave

Not able to find modules

Hi,

After the config, I ran the bot but got the following errors:

23:27 $ hippybot -c hippybot.conf
ERROR: <slot wrapper 'init' of 'object' objects> is not a Python function
Traceback (most recent call last):
File "/Users/kanwu/Documents/workspace/itsi_bot/lib/python2.7/site-packages/hippybot-1.2.7-py2.7.egg/hippybot/bot.py", line 325, in run
bot = HippyBot(self.config._sections)
File "/Users/kanwu/Documents/workspace/itsi_bot/lib/python2.7/site-packages/hippybot-1.2.7-py2.7.egg/hippybot/bot.py", line 89, in init
self.load_plugins()
File "/Users/kanwu/Documents/workspace/itsi_bot/lib/python2.7/site-packages/hippybot-1.2.7-py2.7.egg/hippybot/bot.py", line 235, in load_plugins
getattr(module, 'Plugin').init)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 816, in getargspec
raise TypeError('{!r} is not a Python function'.format(func))
TypeError: <slot wrapper 'init' of 'object' objects> is not a Python function

Here is what my conf file looks like:
[plugins]
load_path = /Users/kanwu/Documents/workspace/itsi_bot/hippybot-1.2.7/hippybot/plugins/
load = rot13

If I change my config file to the following:
[plugins]
load_path = /Users/kanwu/Documents/workspace/itsi_bot/hippybot-1.2.7
load = hippybot.plugins.rot13

I got the following errors
_3:29 $ hippybot -c hippybot.conf
ERROR: No module named rot13
Traceback (most recent call last):
File "/Users/kanwu/Documents/workspace/itsi_bot/lib/python2.7/site-packages/hippybot-1.2.7-py2.7.egg/hippybot/bot.py", line 325, in run
bot = HippyBot(self.config._sections)
File "/Users/kanwu/Documents/workspace/itsi_bot/lib/python2.7/site-packages/hippybot-1.2.7-py2.7.egg/hippybot/bot.py", line 89, in init
self.load_plugins()
File "/Users/kanwu/Documents/workspace/itsi_bot/lib/python2.7/site-packages/hippybot-1.2.7-py2.7.egg/hippybot/bot.py", line 222, in load_plugins
(file, filename, data) = imp.find_module(name, self._load_path)
ImportError: No module named rot13

Is it because my python path was not set properly?

Need to support HipChat server

The code is hard-wired to use the Atlassian HipChat server. There needs to be a config option (not compulsory to make it easy for people already using hippybot) to allow for an in-house HipChat server to be used.

Hippybot is broken under Python 2.7.9

When attempting to run I get:

Traceback (most recent call last):
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/hippybot/bot.py", line 256, in run
    bot = HippyBot(self.config._sections)
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/hippybot/bot.py", line 61, in __init__
    self.join_room(channel, config['connection']['nickname'])
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/hippybot/bot.py", line 166, in join_room
    self.connect().send(pres)
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/jabberbot.py", line 208, in connect
    conres = conn.connect()
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/xmpp/client.py", line 205, in connect
    while not self.TLS.starttls and self.Process(1): pass
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/xmpp/dispatcher.py", line 303, in dispatch
    handler['func'](session,stanza)
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/xmpp/transports.py", line 337, in StartTLSHandler
    self._startSSL()
  File ".../src/work/infrabot/.env/lib/python2.7/site-packages/xmpp/transports.py", line 316, in _startSSL
    tcpsock._sslIssuer = tcpsock._sslObj.issuer()
AttributeError: '_ssl._SSLSocket' object has no attribute 'issuer'

global_commands and command_aliases not functioning

using the example plugin as follows:

hello_world.py

from hippybot.decorators import botcmd, directcmd

class Plugin(object):
global_commands = ['hello_world']
command_aliases = {'hi!' : 'hello'}

@botcmd
def hello_world(self, mess, args):
    return u'Hello world!'

@directcmd
def hello(self, mess, args):
    return u'Well hello there..'
  • bot does not respond to the phrase "hello_world" in normal group room chat.
  • bot does not respond to "hi!" in @ targetted message.
  • bot does respond to "hello_world" in @ targetted message.
  • bot does respond to "hello" in @ targetted message.

I'm inclined to believe an update to jabber has recently broken this functionality, but I can't be sure.

Multiple replies

Currently you can cheat in doing multiple directed replies by just returning a big string with replies on each line, but this is hacky and we can do better.

The better solution would be to allow returning an iterable (tuple, list, generator etc.) from a command, and each is replied in turn.

For @directmd these would all respond to the original user, and just straight posts for @botcmd and @contentcmd.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.