Code Monkey home page Code Monkey logo

will's Introduction

Travis Badge Pypi Badge

Will's smilling face

Meet Will.

Will is the friendliest, easiest-to-teach bot you've ever used. He works on Slack, Hipchat, Rocket.chat, and more - so you can build your bot without platform lock-in.

He makes teaching your chat bot this simple:

@respond_to("hi")
def say_hello(self, message):
    self.say("oh, hello!")

The first version of Will was built by Steven Skoczen while in the Greenkahuna Skunkworks (now defunct), was extended by Ink and Feet and has been contributed to by lots of awesome people.

Will has docs, including a quickstart and lots of screenshots at: http://skoczen.github.io/will/

If you've been using Will 0.x or 1.x, and are wondering how to upgrade to 2.x, here's our friendly guide. :)

Check them out!

will's People

Contributors

acommasplice avatar adamcin avatar adamgilman avatar ashex avatar bfhenderson avatar brandonsturgeon avatar chillipeper avatar ckcollab avatar crccheck avatar d0ugal avatar dmuntean avatar eosman-tibco avatar gordol avatar kenzi avatar mark-adams avatar mvanbaak avatar netjunki avatar puug avatar quixeybrian avatar rbp avatar reist avatar rsalmond avatar shadow7412 avatar sivy avatar skoczen avatar tenzer avatar tomokas avatar unicolet avatar wontonst avatar woohgit 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  avatar  avatar  avatar  avatar  avatar

Watchers

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

will's Issues

roster is empty

Seems that https://github.com/greenkahuna/will/blob/master/will/listener.py#L50 does not block, therefore self.update_will_roster_and_rooms() is called before the self.roster has been set by SleekXMPP. Perhaps you can use the response returned from get_roster() or you can provide a callback to get_roster() which will then call update_will_roster_and_rooms()?

I verified this was the issue by changing https://github.com/fritzy/SleekXMPP/blob/develop/sleekxmpp/clientxmpp.py#L261 to self.event('roster_update', response, direct=True). It seems by default the events are put in a queue which is handle asynchronously (I think).

room list requires admin API access

the room mixin makes a request to https://api.hipchat.com/v1/rooms/list

but this request requires an admin API token according to https://www.hipchat.com/docs/api/auth

My bot user only has Notification access to the v1 hipchat API, so it took me a while to realize why I couldn't join any rooms. It would be nice to mention this in the docs.

If you do only have Notificaiton access you can fake the response with a JSON string similar to this:

{
  "rooms" [{
      "room_id":54321,
      "name":"RoomName",
      "xmpp_jid":"[email protected]"
  }]
}

since these seem to be the only keys needed from the v1/rooms/list response

I got the room ID from here: https://hipchat.com/rooms/ids

maybe this info could be included in the initial env setup, and you could get rid of the v1/rooms/list request all together...

Cannot connect?

Sorry if this is a newbie question.
I've installed Will following the instructions on the very good docs online. I think everything is good (at least it's pretty much all green when I start it).
But then when I look at hipchat, I never see my Will come online or join the room I specified...?
Below are the messages I see. Not sure if the exception in the thread is important? it does not show up only after some time.

$ ./run_will.py 

      ___/-\___
  ___|_________|___
     |         |
     |--O---O--|
     |         |
     |         |
     |  \___/  |
     |_________|

      Will: Hi!


Verifying environment...
  ✓ WILL_USERNAME
  ✓ WILL_PASSWORD
  ✓ WILL_V2_TOKEN
  ✓ WILL_REDIS_URL

Verifying credentials...
  ✓ Chat Bot authenticated
  ✓ @ChatBot verified as handle

Loading configuration...
  Importing config.py... 
    ✓ Valid.
  Verifying settings... 
    - Note: WILL_REDIS_URL not set.  Defaulting to redis://localhost:6379/7.
    ! Warning: no PUBLIC_URL found in the environment or config.  Defaulting to 'http://localhost:9000'.
    ! Warning: no V1_TOKEN found in the environment or config. This is generally ok, but if you have more than 30 rooms, you may recieve rate-limit errors without one.
    ✓ ADMINS
    ✓ DEFAULT_ROOM
    ✓ HANDLE
    ✓ HTTPSERVER_PORT
    ✓ HIPCHAT_SERVER
    ✓ NAME
    ✓ PUBLIC_URL
    ✓ PLUGINS
    ✓ PLUGIN_BLACKLIST
    ✓ PASSWORD
    ✓ REDIS_URL
    ✓ ROOMS
    ✓ TEMPLATE_DIRS_PICKLED
    ✓ USERNAME
    ✓ V2_TOKEN

Verifying rooms...
  ✓ Joining the 1 room specified.

Bootstrapping storage...
  ✓ Connection to redis://localhost:6379/7 successful.

Bootstrapping plugins...

  Administrative actions ------------------------------------------------ will.plugins.admin
    ✓ Say
    ✓ Ping
    ✓ Storage
    ✓ KeepAlive

  Hipchat actions --------------------------------------------------- will.plugins.chat_room
    ✓ Roster
    ✓ Rooms
    ✓ NewTopic

  Devops, server stuff, and uptime ------------------------------------- will.plugins.devops
    ✓ HerokuIsUp
    ✓ EmergencyContacts
    ✓ GithubIsUp

  Old-fashioned friendliness ----------------------------------------- will.plugins.friendly
    ✓ Thanks
    ✓ ItsLove
    ✓ RandomTopic
    ✓ MorninEvenin
    ✓ Hello
    ✓ Snickerdoodles

  Help ------------------------------------------------------------------- will.plugins.help
    ✓ Help
    ✓ ProgrammerHelp

  Plugins -------------------------------------------------------------------------- plugins
    ✓ Hello

  Productivity --------------------------------------------------- will.plugins.productivity
    ✓ Images
    ✓ RemindMe
    ✗ Hangout (blacklisted)
    ✗ Time (blacklisted)

  Web pages --------------------------------------------------------------- will.plugins.web
    ✓ HomePage

Verifying settings requested by plugins...
  ✓ PUBLIC_URL

Bootstrapping complete.

Starting core processes:
  ✓ Web server started.
  ✓ Scheduler started.

Exception in thread Thread-9:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 808, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 761, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/decorators.py", line 26, in wrapped_f
    f(*args, **kwargs)
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/plugins/devops/heroku_is_up.py", line 17, in heroku_is_up
    self.say("Looks like heroku's back up!")
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/plugin.py", line 57, in say
    rooms = self._rooms_from_message_and_room(message, room)
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/plugin.py", line 25, in _rooms_from_message_and_room
    rooms = [self.get_room_from_name_or_id(settings.DEFAULT_ROOM), ]
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/mixins/room.py", line 62, in get_room_from_name_or_id
    for name, room in self.available_rooms.items():
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/mixins/room.py", line 48, in available_rooms
    self.update_available_rooms()
  File "/home/matthieu/virtualenvs/will/local/lib/python2.7/site-packages/will/mixins/room.py", line 29, in update_available_rooms
    for room in rooms["items"]:
KeyError: 'items'

How can I get a list of users in a room?

I've looked through the code and can see there's a list of all the users, but I only want users from the room (or rooms) that Will is in - is this possible?

Thanks,

Mike

Repeating responses on restart

I'm experimenting with will right now so I restart it a lot, and every time it seems to respond again to messages that it had already responded to previously. I'm not sure why it would do that. If there's anything about the config or other information that would be helpful in understanding this, please let me know.

Will wont respond to any msg, exception thrown

I got will up and running. But whenever I mention the user and say hi and hello, this is the exception thrown at the backend and hence nothing happens -

Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 142, in fn
    content = "@%s %s" % (msg.sender["nick"], content)
TypeError: 'NoneType' object has no attribute '__getitem__'

Those are the two commands I tried, not sure about other ones.

OAuth authorization error not raised when authentication fails

This comment is mostly irrelevant; next comment contains the real issue.

Clean install on Ubuntu 12 Vagrant VM install will via pip

ENV VARS (sanitized)

export WILL_USERNAME='[email protected]'
export WILL_PASSWORD='hunter2'
export WILL_TOKEN='admin_token' # Must be an 'admin' token, not just notification.
export WILL_V2_TOKEN='admin_token'
export WILL_ROOMS='roomname'  # Semicolon-separated, so you can have commas in names.
export WILL_DEFAULT_ROOM="[email protected]"
export WILL_NAME='name'  # Must be the *exact, case-sensitive* full name from hipchat.
export WILL_HANDLE='handle'  # Must be the exact handle from hipchat.
export WILL_REDIS_URL="redis://localhost:6379/1"

Receive this error and traceback on console

vagrant@vagrant-ubuntu-precise-64:/vagrant$ sudo ./set_will_env.sh
Bootstrapping plugins...

 FriendlyPlugin:
 - good_night
 - hi
 - morning

 StoragePlugin:
 - clear_all_keys_listener
 - clear_storage
 - db_size
 - show_storage

 HangoutPlugin:
 - hangout

 CookiesPlugin:
 - will_likes_cookies

 RemindMePlugin:
 - remind_me_at

 HelloPlugin:
 - hello

 NewTopicPlugin:
 - new_topic

 KeepAlivePlugin:
 - keep_alive
 - ping
 - ping_keep_alive

 ImagesPlugin:
 - image_me

 RosterPlugin:
 - list_roster

 RoomsPlugin:
 - list_rooms
 - update_rooms

 TimePlugin:
 - what_time_is_it
 - what_time_is_it_in

 HelpPlugin:
 - help
Done.

Bootstrapping bottle...
Bottle v0.12.5 server starting up (using GeventServer())...
Bootstrapping scheduler...
Bootstrapping xmpp...
Listening on http://0.0.0.0:80/
Hit Ctrl-C to quit.

ERROR    Error processing event handler: <bound method WillBot.join_rooms of <will.main.WillBot object at 0x2612910>>
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 53, in join_rooms
    self.update_will_roster_and_rooms()
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 82, in update_will_roster_and_rooms
    user_data = self.full_hipchat_user_list[hipchat_id]
  File "/usr/local/lib/python2.7/dist-packages/will/mixins/hipchat.py", line 83, in full_hipchat_user_list
    for user in r.json()['items']:
KeyError: 'items'
ERROR    Error handling {jabber:client}iq stanza
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 53, in join_rooms
    self.update_will_roster_and_rooms()
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 82, in update_will_roster_and_rooms
    user_data = self.full_hipchat_user_list[hipchat_id]
  File "/usr/local/lib/python2.7/dist-packages/will/mixins/hipchat.py", line 83, in full_hipchat_user_list
    for user in r.json()['items']:
KeyError: 'items'
ERROR    'items'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 53, in join_rooms
    self.update_will_roster_and_rooms()
  File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 82, in update_will_roster_and_rooms
    user_data = self.full_hipchat_user_list[hipchat_id]
  File "/usr/local/lib/python2.7/dist-packages/will/mixins/hipchat.py", line 83, in full_hipchat_user_list
    for user in r.json()['items']:
KeyError: 'items'
127.0.0.1 - - [2014-04-04 18:18:00] "GET /keep-alive HTTP/1.1" 200 126 0.004421

Deploying Will to Heroku

I tried deploying to Heroku using the instructions in the README, but Will went to sleep after a while since there was only 1 web dyno configured. Is there a solution for that?

Will throwing exception & exiting chat - missing user information

I've seen this issue since I first started using Will about 3 months ago.

KeyError: u'1344989'
ERROR    Error processing event handler: <bound method WillBot.join_rooms of <will.main.WillBot object at 0x7fba76674c50>>
Traceback (most recent call last):
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1699, in _event_runner
    func(*args)
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 55, in join_rooms
    self.update_will_roster_and_rooms()
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 85, in update_will_roster_and_rooms
    user_data = self.full_hipchat_user_list[hipchat_id]
KeyError: u'1344989'
ERROR    Error handling {jabber:client}iq stanza
Traceback (most recent call last):
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1699, in _event_runner
    func(*args)
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 55, in join_rooms
    self.update_will_roster_and_rooms()
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 85, in update_will_roster_and_rooms
    user_data = self.full_hipchat_user_list[hipchat_id]
KeyError: u'1344989'
ERROR    u'1344989'
Traceback (most recent call last):
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1699, in _event_runner
    func(*args)
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 55, in join_rooms
    self.update_will_roster_and_rooms()
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 85, in update_will_roster_and_rooms
    user_data = self.full_hipchat_user_list[hipchat_id]
KeyError: u'1344989'

Redis Configuration

What sort of configuration does redis need to be in? Does will use it as a cache and we should expire old events or does it use it more like a datastore?

Pass on message automatically

Sure would be nice if we didn't have to pass message around, and it could be passed through via the decorators. See if that's possible in a simple, reliable way.

SyntaxError: invalid syntax with sorted_help in main.py

If I remove lines 329 & 330, the bot fires up, but help errors out.

(18:31:57)-> ./qabot.py
Traceback (most recent call last):
File "./qabot.py", line 2, in
from will.main import WillBot
File "/home/cpsaurus/will/will/main.py", line 329
sorted_help = {k: sorted(v) for k,v in self.help_modules.items()}
^
SyntaxError: invalid syntax
(18:33:41)-> python -V
Python 2.6.6

On User Connect

Is there a way for Will Bot to "listen" to when users connect?

generate_will_project gives pkg_resources.VersionConflict

I followed the instructions on the quickstart page (http://skoczen.github.io/will/). Pip appears to have installed Will and all prerequisites correctly. The final message was:

Successfully installed will APScheduler Fabric Jinja2 Markdown MarkupSafe PyYAML argh args bottle clint dill dnspython ecdsa futures gevent ghp-import greenlet hiredis mkdocs natural paramiko parsedatetime pathtools pyandoc pyasn1 pyasn1-modules pycrypto pytz redis requests six sleekxmpp tzlocal watchdog
Cleaning up...

When I ran generate_will_project, I got this:

(will-bot)~/will-bot$ generate_will_project 
Traceback (most recent call last):
  File "/opt/.envs/will-bot/bin/generate_will_project", line 5, in 
    from pkg_resources import load_entry_point
  File "/opt/.envs/will-bot/local/lib/python2.7/site-packages/pkg_resources.py", line 2829, in 
    working_set = WorkingSet._build_master()
  File "/opt/.envs/will-bot/local/lib/python2.7/site-packages/pkg_resources.py", line 451, in _build_master
    return cls._build_from_requirements(__requires__)
  File "/opt/.envs/will-bot/local/lib/python2.7/site-packages/pkg_resources.py", line 464, in _build_from_requirements
    dists = ws.resolve(reqs, Environment())
  File "/opt/.envs/will-bot/local/lib/python2.7/site-packages/pkg_resources.py", line 643, in resolve
    raise VersionConflict(dist, req) # XXX put more info here
pkg_resources.VersionConflict: (Jinja2 2.7.3 (/opt/.envs/will-bot/lib/python2.7/site-packages), Requirement.parse('Jinja2==2.7.1'))

Any ideas? If this helps, uname gives:

Linux my-server 3.13.0-36-generic #63-Ubuntu SMP Wed Sep 3 21:30:07 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

It's python 2.7.6.

Reminders containing the word 'at' confuse will

The regex for Will's remind_me.py plugin needs adjusted to allow reminder messages to contain the word 'at'. Currently, I believe Will truncates the message at the first 'at' he encounters.

Example:

[Mar-6 5:11 PM] Levi Thomason: @will remind me to ask everyone to yell at me until I really do my expense report for Andrew at 11:00 AM tomorrow
[Mar-6 5:11 PM] William T. Kahuna: ask everyone to yell tomorrow at 11am. Got it.

This may also be the case for the work 'on'. If/when I get more time I can offer some possible variation.

AttributeError: 'module' object has no attribute 'PLUGINS'

When attempting to run_will.py, the following error is generated:

Traceback (most recent call last):
File "./run_will.py", line 5, in
bot = WillBot()
File "/tmp/will/will/main.py", line 63, in init
plugins = settings.PLUGINS
AttributeError: 'module' object has no attribute 'PLUGINS'
Exception KeyError: KeyError(27928528,) in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored

This is from the current pull from here. And from what I can tell settings under ./will/settings.py, does not have a PLUGIN function. Thoughts?

generate_will_project fails to find sleekxmpp, OS X 10.9.2

I saw in #9 that someone else had a similar issue, but unfortunately mine isn't magically solved by running inside virtualenv.

Just like the other poster:

Traceback (most recent call last):
  File "/usr/local/bin/generate_will_project", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 2607, in <module>
    parse_requirements(__requires__), Environment()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 565, in resolve
    raise DistributionNotFound(req)  # XXX put more info here
pkg_resources.DistributionNotFound: sleekxmpp==1.2.4

I definitely have it installed, though:

$ pip list
APScheduler (2.1.2)
bottle (0.12.5)
dill (0.2b1)
dnspython (1.11.1)
gevent (1.0)
greenlet (0.4.2)
hiredis (0.1.2)
Jinja2 (2.7.2)
MarkupSafe (0.23)
natural (0.1.4)
parsedatetime (1.1.2)
pip (1.5.5)
pyasn1 (0.1.7)
pyasn1-modules (0.0.5)
redis (2.9.1)
requests (2.2.1)
setuptools (3.4.4)
sleekxmpp (1.2.4)
will (0.4.6)
wsgiref (0.1.2)

All of this is inside of a virtual environment made just for will, and persists across multiple virtual envs and runs of generate_will_project.

Web Server Started followed by error.

Hello,

I'm unable to get Will running, I've got the config setup, all green ticks, but just after it says "Web server started" I get this:

Starting core processes:
  ✓ Web server started.
Process Process-3:
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.7_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/local/Cellar/python/2.7.7_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/will/main.py", line 323, in bootstrap_bottle
    bottle.run(host='0.0.0.0', port=settings.HTTPSERVER_PORT, server='gevent', quiet=True)
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/bottle.py", line 3112, in run
    server.run(app)
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/bottle.py", line 2903, in run
    server.serve_forever()
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/gevent/baseserver.py", line 282, in serve_forever
    self.start()
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/gevent/baseserver.py", line 234, in start
    self.init_socket()
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/gevent/pywsgi.py", line 639, in init_socket
    StreamServer.init_socket(self)
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/gevent/server.py", line 78, in init_socket
    self.socket = self.get_listener(self.address, self.backlog, self.family)
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/gevent/server.py", line 89, in get_listener
    return _tcp_listener(address, backlog=backlog, reuse_addr=self.reuse_addr, family=family)
  File "/Users/mikepearce/Envs/my_will/lib/python2.7/site-packages/gevent/server.py", line 153, in _tcp_listener
    sock.bind(address)
  File "<string>", line 1, in bind
error: [Errno 13] Permission denied: ('0.0.0.0', 80)

Will doesn't seem to be connecting to HipChat, so I'm hoping it's this that is the problem.

Thanks,

Mike

Bundle up will's deploy capabilities as a module

GK uses will to manage, stage, and deploy a variety of codebases on heroku. We have a set of will plugins that largely abstract out all the heroku config, and let anyone at the company do stuff like:

@will stage new-branch, and get a running stack in minutes.

This issue is for us to decouple the bits that are tied to our config, and offer this as a module for will, generally.

KeyError: 'mention_name'

My bot seems to be unable to join a room. It connects OK, then sits for a minute and says:

ERROR    Error processing event handler: <bound method WillBot.join_rooms of <will.main.WillBot object at 0x31adb10>>
Traceback (most recent call last):
  File "/opt/deploybot/venv/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/opt/deploybot/venv/local/lib/python2.7/site-packages/will/listener.py", line 54, in join_rooms
    self.update_will_roster_and_rooms()
  File "/opt/deploybot/venv/local/lib/python2.7/site-packages/will/listener.py", line 78, in update_will_roster_and_rooms
    internal_roster[user_id].nick = user_data["mention_name"]
KeyError: 'mention_name'
ERROR    Error handling {jabber:client}iq stanza
Traceback (most recent call last):
  File "/opt/deploybot/venv/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/opt/deploybot/venv/local/lib/python2.7/site-packages/will/listener.py", line 54, in join_rooms
    self.update_will_roster_and_rooms()
  File "/opt/deploybot/venv/local/lib/python2.7/site-packages/will/listener.py", line 78, in update_will_roster_and_rooms
    internal_roster[user_id].nick = user_data["mention_name"]
KeyError: 'mention_name'

I'm guessing from "mention_name" that it's related to WILL_HANDLE, but I'm printing it out in the app and it is correct. I've tripled checked it, tried changing the @name on the hipchat server to something else, changing it in will, etc etc... Nothing works.

Project missing tags for recent releases

I usually check the releases page to see what the current version of will is, but it's still stuck on 0.4.10. Bringing that up to date will make it easier for people to know what the current release is and see what changed between versions.

Room topics not refreshed/updated

In my @HEAR handler, I'm trying to fetch the current room topic (by accessing the room attribute of the message object) so I can modify it instead of replacing it entirely. However, it looks like will only fetches the room list once on startup, and doesn't update the 'topic' attribute if a user changes it manually using the /topic command.

image me fails frequently (suspected throttling on google end)

I get this quite a bit:

Traceback (most recent call last):
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/listener.py", line 148, in fn
    listener["fn"](*args, **kwargs)
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/decorators.py", line 6, in wrapped_f
    f(*args, **kwargs)
  File "/home/meatbot/.virtualenvs/meatbot/local/lib/python2.7/site-packages/will/plugins/productivity/images.py", line 19, in image_me
    results = r.json()["responseData"]["results"]
TypeError: 'NoneType' object has no attribute '__getitem__'

But google image search does return images. This has been happening with the search term "jim webber" today, with will==0.5.7

Is it possible my bot is being throttled?

Can a plugin leave a room?

I'd like to write a plugin that can have Will leave a room, but it doesn't seem possible at present.

Current plugins seem to only do things using the HipChat API, not the XMPP client, and they don't seem to have access to the WillBot object, which they'd need to get to the XEP_0045 plugin and call leaveMUC.

I could modify plugin initialization to pass in the WillBot object, but I wonder if there's some reason plugins don't have access to it now.

scheduler excepts saying it doesn't have an attribute "start_hour"

i copied the @random example but i'm seeing an error on startup, and it never triggers:

This is the listener:
@Randomly(start_hour='6', end_hour='17', day_of_week="mon-fri", num_times_per_day=8)

Exception:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(_self._args, *_self._kwargs)
File "/home/jude/.virtualenvs/mwill/local/lib/python2.7/site-packages/will/main.py", line 305, in bootstrap_scheduler
self.scheduler.start_loop(self)
File "/home/jude/.virtualenvs/mwill/local/lib/python2.7/site-packages/will/scheduler.py", line 30, in start_loop
self.check_scheduled_actions()
File "/home/jude/.virtualenvs/mwill/local/lib/python2.7/site-packages/will/scheduler.py", line 95, in check_scheduled_actions
self.add_random_tasks(plugin_info["full_module_name"], plugin_info["name"], function_name, fn.start_hour, fn.end_hour, fn.day_of_week, fn.num_times_per_day)
AttributeError: 'function' object has no attribute 'start_hour'

Respond back when Will doesn't understand a direct message

Sometimes users of our bot mistype things and will just goes silent. Would be nice to have it respond with some default "I don't what you are talking about" message, if it's a directed message that doesn't match any of the @respond_to regexes.

Will plugins with more than one listener can't save state

Every @HEAR() or @respond_to() decorator is causing a new instance of the plugin to be created. My plugin needs to share state between the different methods, so this breaks my plugin unless I use the load/save storage backend, which is overkill for what I'm doing. Would it be hard to change the code to create a single instance of each plugin class instead of one per listener?

SyntaxError on first run

I'm getting a syntax error on a clean VM when running Will for the first time - this was repeatable on multiple machines:

# ./run_will.py
Traceback (most recent call last):
  File "./run_will.py", line 2, in <module>
    from will.main import WillBot
  File "/usr/lib/python2.6/site-packages/will/main.py", line 329
    sorted_help = {k: sorted(v) for k,v in self.help_modules.items()}
                                  ^

Am I missing dependancies somewhere?

Will Bot cannot handle responses from webhooks

When trying to integrate will bot to respond to pagerduty webhook in chat, get this error (regardless of self.say() or self.reply())

I suspect it has something to do with the fact that will doesn't have a sender name or nick to respond to.

DEBUG Event triggered: muc::[email protected]::message
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 551, in *bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 504, in run
self.__target(_self.__args, _self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/will/listener.py", line 153, in fn
content = "@%s %s" % (msg.sender["nick"], content)
TypeError: 'NoneType' object has no attribute '__getitem
'

Will 0.5 Omnibus issue!

So there have been a number of thoughts swirling in various issues about easier config, disabling/enabling rooms, disabling/enabling plugins, and how to easily develop, debug, and deploy will. This issue aims to pull all of that together, with a cohesive target.

Big things for this release:

  1. Proper configuration support, as mentioned in #14, #31, #36, #11, and half the human race. Draft is below.
  2. Better documentation on how to set will up in a dev environment, including best-practices for room config, team env control, etc.
  3. Better documentation on how to set will up in a production environment, including best-practices for test running, updates, and deployment.
  4. Better bootstrapping script, to generate base config files, and set up dev and production-ready config for will.

First draft of config.py:

# Welcome to Will's settings.  You'll need to set a few settings below,
# with some optional ones further down.
# ------------------------------------------------------------------------------------
# Required
# ------------------------------------------------------------------------------------
# The following four settings must be set for will to work.

# This is the list of rooms will should join.
ROOMS = ['Testing, Will Kahuna', 'GreenKahuna']
# Default: ALL_ROOMS

# This is the room will will talk to if the trigger 
# is a webhook and he isn't told a specific room. 
# Defaults to the first of ROOMS.
DEFAULT_ROOM = 'GreenKahuna'

# If will isn't accessible at localhost, you must set this for his keepalive to work.
PUBLIC_URL = "http://my-will.herokuapp.com"  # Note no trailing slash.


# This is the list of plugins will should load. This list can contain:
# 
# Built-in core plugins:
# ----------------------
# All built-in modules:     will/plugins
# Built-in modules:         will/plugins/module_name
# Specific plugins:         will/plugins/module_name/plugin.py
#
# Plugins in your will:
# ----------------------
# All modules:              my_will/plugins
# A specific module:        my_will/plugins/module_name
# Specific plugins:         my_will/plugins/module_name/plugin.py

PLUGINS = [
    "will/plugins",
    "my_will/plugins",
]


# All plugins are enabled by default, unless in this list
PLUGIN_BLACKLIST = [
    # Who would deprive will of cookies??
    # "will/friendly/cookies.py",
]


# Where will should look for templates
TEMPLATE_DIRS = [
    "will/templates",
    "my_will/templates",
]


# ------------------------------------------------------------------------------------
# Optional
# ------------------------------------------------------------------------------------

# User handles who are allowed to perform "admin" actions.  Defaults to everyone.
# ADMIN_HANDLES = [
#     "steven",
#     "levi",
# ]

# Port to listen to (defaults to $PORT, then 80.) Set > 1024 to run without elevated permission.
# HTTPSERVER_PORT = "80"  


# Email address to send from, if your will sends emails.
# WILL_DEFAULT_FROM_EMAIL = "[email protected]"

Note: I (@skoczen) won't have proper cycles to implement this stuff until the week of June 23. However, in that week, I will have enough cycles to hopefully get it done. PRs, ideas, and code welcome in the meantime!

KeyError: 'xmpp_jid'

This behavior comes and goes between invocations of my bot, but frequently I see the following error whenever will receives a private message. This stops my plugins from executing and I have to restart will to recover. FWIW, we're using a locally-hosted hipchat instance, but there's nothing else weird about our config. Let me know if you'd like additional log output.

ERROR    Error processing event handler: <bound method WillBot.message_recieved of <will.main.WillBot object at 0x7f6117bc9bd0>>
Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 102, in message_recieved
    self._handle_message_listeners(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 133, in _handle_message_listeners
    msg.room = self.get_room_from_message(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 59, in get_room_from_message
    return self.get_room_by_jid(message.getMucroom())
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 54, in get_room_by_jid
    if room["xmpp_jid"] == jid:
KeyError: 'xmpp_jid'
ERROR    Error handling {jabber:client}message stanza
Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 102, in message_recieved
    self._handle_message_listeners(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 133, in _handle_message_listeners
    msg.room = self.get_room_from_message(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 59, in get_room_from_message
    return self.get_room_by_jid(message.getMucroom())
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 54, in get_room_by_jid
    if room["xmpp_jid"] == jid:
KeyError: 'xmpp_jid'
ERROR    'xmpp_jid'
Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 102, in message_recieved
    self._handle_message_listeners(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 133, in _handle_message_listeners
    msg.room = self.get_room_from_message(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 59, in get_room_from_message
    return self.get_room_by_jid(message.getMucroom())
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 54, in get_room_by_jid
    if room["xmpp_jid"] == jid:
KeyError: 'xmpp_jid'
ERROR    Error processing event handler: <bound method WillBot.message_recieved of <will.main.WillBot object at 0x7f6117bc9bd0>>
Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 102, in message_recieved
    self._handle_message_listeners(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 133, in _handle_message_listeners
    msg.room = self.get_room_from_message(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 59, in get_room_from_message
    return self.get_room_by_jid(message.getMucroom())
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 54, in get_room_by_jid
    if room["xmpp_jid"] == jid:
KeyError: 'xmpp_jid'
ERROR    Error handling {jabber:client}message stanza
Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 102, in message_recieved
    self._handle_message_listeners(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 133, in _handle_message_listeners
    msg.room = self.get_room_from_message(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 59, in get_room_from_message
    return self.get_room_by_jid(message.getMucroom())
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 54, in get_room_by_jid
    if room["xmpp_jid"] == jid:
KeyError: 'xmpp_jid'
ERROR    'xmpp_jid'
Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/sleekxmpp/xmlstream/xmlstream.py", line 1693, in _event_runner
    func(*args)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 102, in message_recieved
    self._handle_message_listeners(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/listener.py", line 133, in _handle_message_listeners
    msg.room = self.get_room_from_message(msg)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 59, in get_room_from_message
    return self.get_room_by_jid(message.getMucroom())
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/room.py", line 54, in get_room_by_jid
    if room["xmpp_jid"] == jid:
KeyError: 'xmpp_jid'

"Unable to remove task"

Intermittently, my will instance starts printing these errors every few minutes after starting up (and without any activity happening with my plugins).

CRITICAL Unable to remove task. Leaving it in, you'll have to clean it out by hand. Sorry!

Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/scheduler.py", line 78, in _run_applicable_actions_in_list
    self.bot.remove_from_schedule(item["hash"], periodic_list=periodic_list)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/schedule.py", line 81, in remove_from_schedule
    del sched_list[item_hash]
KeyError: -3340279509489936209

Continuing...

CRITICAL Unable to remove task. Leaving it in, you'll have to clean it out by hand. Sorry!

Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/scheduler.py", line 78, in _run_applicable_actions_in_list
    self.bot.remove_from_schedule(item["hash"], periodic_list=periodic_list)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/schedule.py", line 81, in remove_from_schedule
    del sched_list[item_hash]
KeyError: -1340245509339936023

Continuing...

CRITICAL Unable to remove task. Leaving it in, you'll have to clean it out by hand. Sorry!

Traceback (most recent call last):
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/scheduler.py", line 78, in _run_applicable_actions_in_list
    self.bot.remove_from_schedule(item["hash"], periodic_list=periodic_list)
  File "/home/austin/.virtualenvs/willbot/local/lib/python2.7/site-packages/will/mixins/schedule.py", line 81, in remove_from_schedule
    del sched_list[item_hash]
KeyError: -8340306509534935736

Continuing...

Unable to save / Major startup failure.

When I try to run will, I hit a ton of exceptions. All related I think.

Context: Trying to run will locally. Redis up and running & accessible. Brand new python2.7 install.

Will install process:

# brand new environment with python2.7 freshly installed.
cd /will
pip install -r requirements.txt
pip install will
generate_will_project
# export env
./run_will.py
Starting core processes:
  ✓ Web server started.
CRITICAL Unable to save plugin_modules_library:
Traceback (most recent call last):
  File "/src/will/mixins/storage.py", line 37, in save
    ret = self.storage.set(key, pickle.dumps(value))
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 1055, in set
    return self.execute_command('SET', *pieces)
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 562, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 874, in get_connection
    connection = self.make_connection()
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 883, in make_connection
    return self.connection_class(**self.connection_kwargs)
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 393, in __init__
    self.port = int(port)
TypeError: int() argument must be a string or a number, not 'NoneType'

.... (A lot like that)

CRITICAL Unable to save will_periodic_times_list:
Traceback (most recent call last):
  File "/src/will/mixins/storage.py", line 37, in save
    ret = self.storage.set(key, pickle.dumps(value))
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 1055, in set
    return self.execute_command('SET', *pieces)
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 562, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 874, in get_connection
    connection = self.make_connection()
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 881, in make_connection
    raise ConnectionError("Too many connections")
ConnectionError: Too many connections

... (A lot again)

Then next section:

  ✓ Scheduler started.
WARNING  Unable to load last_random_schedule
CRITICAL Unable to save last_random_schedule:
Traceback (most recent call last):
  File "/src/will/mixins/storage.py", line 37, in save
    ret = self.storage.set(key, pickle.dumps(value))
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 1055, in set
    return self.execute_command('SET', *pieces)
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 562, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 874, in get_connection
    connection = self.make_connection()
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 881, in make_connection
    raise ConnectionError("Too many connections")
ConnectionError: Too many connections

Then it is basically an infinite loop of exceptions. When interrupting:

WARNING  Unable to load will_schedule_times_list
WARNING  Unable to load will_periodic_times_list
CRITICAL Unable to save scheduler_lock:
Traceback (most recent call last):
  File "/src/will/mixins/storage.py", line 37, in save
    ret = self.storage.set(key, pickle.dumps(value))
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 1055, in set
    return self.execute_command('SET', *pieces)
  File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 562, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 874, in get_connection
    connection = self.make_connection()
  File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 881, in make_connection
    raise ConnectionError("Too many connections")
ConnectionError: Too many connections

^CKeyboardInterrupt
KeyboardInterrupt
  ✓ Chat client started.
  ✓ Will is running.
KeyboardInterrupt
DEBUG    Starting HANDLER THREAD


Received keyboard interrupt, quitting threads..Exception KeyError: KeyError(139970250096720,) in <module 'threading' from '/usr/local/lib/python2.7/threading.pyc'> ignored

generate_will_project aborts on osx 10.9.2

Trying to use will on a project and running generate_will_project on osx 10.9.2 causes this exception:

Traceback (most recent call last):
  File "/usr/local/bin/generate_will_project", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 2603, in <module>
    working_set.require(__requires__)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 666, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 565, in resolve
    raise DistributionNotFound(req)  # XXX put more info here
pkg_resources.DistributionNotFound: apscheduler

Any ideas what's going on? pip install got me will (0.4.2).

Allow disabling built-in plugins

Currently the plugins distributed with will are always active. There should be a way to enable the user to disable them (either because their functionality is undesirable, or because the user wants to customise their behaviour).

I can submit a pull request for this. The idea is to add a flag to WillBot.init, and pass it on run_will.

Target user not a valid user

When I try to start will, I always hit a credentials issue.

Verifying credentials...
ERROR: We ran into trouble: 'Target user bot not a valid user'

I double, triple checked the credentials and they are correct. I regenerated the token v2, I even requested a token v1, but no luck.

Any idea what is going on or how I could know more?

Note: I log in with Hipchat using [email protected]. I tried WILL_USERNAME as bot and [email protected], but no luck there.

Doing work in a plugin __init_() hangs startup

With this code:

class H5Handoff(WillPlugin):
    def __init__(self):
        self.h5s_heard = []
         r = redis.Redis()
        try:
            res = json.loads(r.get("current_sre_oncall"))
            self.current = res
        except Exception as e:
            logger.warning("failed to fetch oncall: %s", e)
            return None

Will never starts up, or even begins writing to redis for the scheduler lock. It hangs after print this to the console:

Starting core processes
  ✓ Web server started.
  ✓ Scheduler started.

Removing the redis call makes it startup cleanly again. Moving this code into a different method and invoking it after startup via @HEAR works fine. I'm not sure if it's because I'm talking to redis, doing I/O in general, or what.

Tests

And maybe a CONTRIBUTING.md with style guides and conventions?

Ability to have have detailed help strings, and not show all functions

I'd like the ability to have some functions of Will not show up in the 'help' command, and have a way to write the documentation manually for what each function does.

eg.

to Will: help
Here's everything I know how to listen to:
new topic : Sets the room's topic to the string specified.
what time is it? or what time is it in : Tells you the time where the server is by default or the specified location.

Where now it displays things like the regex, no context of what it does, etc.

I'm happy to work on this and PR it. I think it's easily done with doc strings and some munging of the way help outputs the data if there are no objections.

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.