Coder Social home page Coder Social logo

robut's Introduction

<img src=“https://travis-ci.org/justinweiss/robut.svg?branch=master” alt=“Build Status” />

Robut

The friendly plugin-enabled HipChat bot.

Installation and usage

Robut can be installed by running gem install robut. This installs the robut binary. When run, robut reads a Chatfile, connects to the specified HipChat server and chatroom, and feeds every line said in the chatroom through the plugins configured by the Chatfile.

Once robut is running, the plugins listen to what’s being said in the chatroom. Most plugins listen for @replies to robut:

@robut lunch? # => "Banh Mi!"
@robut calc 1 + 1 # => 2

Others listen to everything, and don’t require an @reply.

Some of the included plugins require extra gems to be installed:

Robut::Plugin::TWSS

requires the twss gem.

Robut::Plugin::Calc

requires the calc gem.

Robut::Plugin::Weather

requires the nokogiri gem.

Robut::Plugin::GoogleImages

requires the google-search gem.

A list of known 3rd-party plugins is available on the wiki: github.com/justinweiss/robut/wiki/Robut-Plugins Feel free to add your own creations!

The Chatfile

When the robut command runs, it looks for and evals ruby code in a file called Chatfile in the current directory. You can override the configuration file by passing robut a path to a Chatfile as the first parameter:

robut /path/to/Chatfile

The Chatfile is just ruby code. A simple example can be found here: Chatfile

Robut::Web

You can run Robut as a rack application, which allows it to accept incoming post requests (e.g. Heroku deploy hooks, GitHub post-recieve hooks, etc.) that can send messages to all connected rooms. Have a look at config.ru for an example.

Adding and configuring plugins

Plugins are ruby classes, so enabling a plugin just requires requiring the plugin file, optionally configuring the plugin class, and adding the class to the global plugin list:

require 'robut/plugin/lunch'
Robut::Plugin::Lunch.places = ["Banh Mi", "Mad Oven", "Mod Pizza", "Taphouse"]
Robut::Plugin.plugins << Robut::Plugin::Lunch

Each plugin can be configured differently, or not at all. It’s best to look at the docs for the plugins you want to use to figure out what kind of configuration they support.

Some plugins might require storage (like the ‘lunch` plugin). You can configure the type of storage you want to use based on the need for persistence. The default is the HashStore which is in-memory only. Below is an example of using the YamlStore.

Robut::Connection.configure do |config|
  # ...
  Robut::Storage::YamlStore.file = "~/.robut_store"
  config.store = Robut::Storage::YamlStore
end

Configuring the HipChat connection

The Chatfile also configures the HipChat connection. This is done in a Robut::Connection.configure block:

# Configure the robut jabber connection and you're good to go!
Robut::Connection.configure do |config|
  config.jid = '[email protected]/bot'
  config.password = 'password'
  config.nick = 'Bot Nick'
  config.rooms = ['[email protected]', '[email protected]']

  # Custom @mention name
  config.mention_name = 'Bot'

  # Example of the YamlStore which uses a yaml file for persistence
  Robut::Storage::YamlStore.file = "~/.robut_store"
  config.store = Robut::Storage::YamlStore

  # Add a logger if you want to debug the connection
  # config.logger = Logger.new(STDOUT)
end

This block usually goes at the end of the Chatfile.

Built-in plugins

Robut includes a few plugins that we’ve found useful:

Robut::Plugin::Calc

a simple calculator.

@robut calc 1 + 1 # => 2
Robut::Plugin::Lunch

a random decider for lunch locations.

@robut lunch? # => "Banh Mi!"
Robut::Plugin::Meme

generates meme images using memecaptain.

@robut meme all_the_things drink; all the beer
Robut::Plugin::GoogleImages

does a google image search for a query and returns the first result.

@robut image ship it
Robut::Plugin::Sayings

a simple regex listener and responder.

You're the worst robot ever, @robut. # => I know.
Robut::Plugin::TWSS

an interface to the TWSS gem. Listens to anything said in the chat room and responds “That’s what she said!” where appropriate.

well hurry up, you're not going fast enough # => "That's what she said!"
Robut::Plugin::Echo

echo back whatever it gets.

@robut echo hello world # => "hello world"
Robut::Plugin::Say

invokes the “say” command (text-to-speech).

@robut say this rocks # (make sure robut is running on a machine with speakers :)
Robut::Plugin::Ping

responds with “pong”.

@robut ping # => "pong"
Robut::Plugin::Later

performs the given command after waiting an arbitrary amount of time.

@robut in 5 minutes echo @justin wake up! # => (5 minutes later) "@justin wake up!"
Robut::Plugin::Weather

uses Google Weather to fetch for the weather for a given location and day.

@robut seattle weather saturday? # => "Forecast for Seattle, WA on Sat: Sunny, High: 77F, Low: 55F"
Robut::Plugin::Alias

creates aliases to other robut commands.

@robut alias "cowboy" "@robut play bon jovi wanted dead or alive" # Cuz somtimes you need it.
@robut alias w weather? # less typing for common stuff
Robut::Plugin::Quips

stores and posts Bugzilla-style quips.

@robut add quip It was great when I wrote it!
@robut quip # => It was great when I wrote it!
@robut remove quip It was great when I wrote it!
Robut::Plugin::Help

lists usage for all the plugins loaded into robut

@robut help # => command usage

Writing custom plugins

You can supply your own plugins to Robut. To create a plugin, include the Robut::Plugin module and implement the handle(time, sender_nick, message) to perform any plugin-specific logic.

Robut::Plugin provides a few helper methods that are documented in its class definition.

Contributing

To test your changes:

  1. Install Bundler

  2. Run ‘bundle install`

  3. Make your changes and run ‘bundle exec ruby -Ilib bin/robut ~/MyTestingChatfile`

  4. Add tests and verify by running ‘bundle exec rake test`

Once your changes are ready:

  1. Fork robut

  2. Create a topic branch: ‘git checkout -b my_branch`

  3. Commit your changes

  4. Push to your branch: ‘git push origin my_branch`

  5. Send me a pull request

  6. That’s it!

Todo

  • More plugins!

robut's People

Contributors

bvandenbos avatar chingor13 avatar ejholmes avatar elstgav avatar jbussdieker avatar joshgoebel avatar jparise avatar justinweiss avatar powdahound avatar radamant avatar slant avatar stevenharman avatar vrish88 avatar will 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

robut's Issues

Get message sender in plugin

I don't know if this is possible but would love to get the message sender in a plugin even when it's not a private message.

Respond to direct messages without @robut

In direct messages it's redundant (and annoying) to use "@robut" for every command. It'd be great to issue the commands sans @ name for quicker messaging, e.g.

image example vs. @robut image example

private hipchat servers?

Do you know off hand how to get robut to join private hipchat servers? I've only done a little bit of digging so far, and it looks like it's passing in the jid to the jabberthing, and that is how it knows where to connect.

On a private hipchat server the jid is @chat.btf.hipchat.com even when the server is at your.whatever.com.

I suspect there is some way to alter that with the jabber library, but I figured I'd ask first before digging.

Access the room id from inside a plugin

Is it possible to get the room ID from inside a plugin?

I'd like to restrict some plugins to some rooms.

Also, is it possible to access the user JID as well from within a plugin?

Feature: dev console

Would be neat to have something like rake console to get a bot dev console, where the bot would parse every written line as a chat message. For local/offline development of plugins.

Can't connect

It seems I'm timing out trying to establish the SSL connection.

  • desktop app works, so I don't think its a network/firewall issue.
  • Ruby 1.9.3 on Win7/32 bit
  • Robut 0.30.0 from gem
  • Chatfile:
# Require your plugins here
require 'robut/plugin/twss'
require 'robut/plugin/calc'
require 'robut/plugin/ping'
require 'robut/storage/yaml_store'

# Add the plugin classes to the Robut plugin list.
# Plugins are handled in the order that they appear in this array.
Robut::Plugin.plugins << Robut::Plugin::TWSS
Robut::Plugin.plugins << Robut::Plugin::Calc 
Robut::Plugin.plugins << Robut::Plugin::Ping

# Configure the robut jabber connection and you're good to go!
Robut::Connection.configure do |config|
  # Note that the jid must end with /bot if you don't want robut to 
  # spam the channel, as described by the last bullet point on this 
  # page: https://www.hipchat.com/help/category/xmpp
  config.jid = '[email protected]/bot'
  config.password = 'xxx'
  config.nick = 'xxx'
  config.room = '[email protected]'

  # Some plugins require storage
  Robut::Storage::YamlStore.file = ".robut"
  config.store = Robut::Storage::YamlStore

  # Add a logger if you want to debug the connection
  config.logger = Logger.new(STDOUT)
end
  • output:
g:\eddynet\projects\dev_utilities\robut>robut
D, [2012-07-02T11:26:23.258337 #13000] DEBUG -- : Debugging mode enabled.
W, [2012-07-02T11:26:23.258337 #13000]  WARN -- : Warnings mode enabled.
D, [2012-07-02T11:26:23.259338 #13000] DEBUG -- : RESOLVING:
    _xmpp-client._tcp.chat.hipchat.com (SRV)
D, [2012-07-02T11:26:24.762424 #13000] DEBUG -- : CONNECTING:
    chat.hipchat.com:5222
D, [2012-07-02T11:26:24.859429 #13000] DEBUG -- : SENDING:
    <stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='chat.hipchat.com' xml:lang=
'en' version='1.0' >
D, [2012-07-02T11:26:24.954435 #13000] DEBUG -- : RECEIVED:
    <stream:stream from='chat.hipchat.com' id='578cb95a5c9985e6' xmlns:stream='http://etherx.jabber.org/streams' version
='1.0' xmlns='jabber:client'/>
D, [2012-07-02T11:26:24.955435 #13000] DEBUG -- : RECEIVED:
    <stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls></stream:features>
D, [2012-07-02T11:26:24.955435 #13000] DEBUG -- : FEATURES: received
D, [2012-07-02T11:26:24.956435 #13000] DEBUG -- : PROCESSING:
    <stream:features xmlns='jabber:client'><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls></str
eam:features> (REXML::Element)
D, [2012-07-02T11:26:24.956435 #13000] DEBUG -- : TRYING stanzacbs...
D, [2012-07-02T11:26:24.956435 #13000] DEBUG -- : TRYING message/iq/presence/cbs...
D, [2012-07-02T11:26:24.957435 #13000] DEBUG -- : FEATURES: waiting...
D, [2012-07-02T11:26:24.957435 #13000] DEBUG -- : FEATURES: waiting finished
D, [2012-07-02T11:26:24.958435 #13000] DEBUG -- : SENDING:
    <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
D, [2012-07-02T11:26:25.059441 #13000] DEBUG -- : RECEIVED:
    <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
D, [2012-07-02T11:26:25.060441 #13000] DEBUG -- : TLSv1: OpenSSL handshake in progress
D, [2012-07-02T11:28:55.041019 #13000] DEBUG -- : TLSv1: restarting parser
D, [2012-07-02T11:28:55.041019 #13000] DEBUG -- : SENDING:
    <stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='chat.hipchat.com' xml:lang=
'en' version='1.0' >
W, [2012-07-02T11:28:55.042019 #13000]  WARN -- : EXCEPTION:
    Jabber::ServerDisconnected
    Server Disconnected!
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/streamparser.rb:68:in `block in parse'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `call'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `block in handle'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `each'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `handle'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:95:in `parse'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/streamparser.rb:79:in `parse'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:75:in `block in start'
W, [2012-07-02T11:28:55.043019 #13000]  WARN -- : Exception caught in Parser thread! (Jabber::ServerDisconnected)
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/streamparser.rb:68:in `block in parse'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `call'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `block in handle'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `each'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:195:in `handle'
    G:/Ruby193/lib/ruby/1.9.1/rexml/parsers/sax2parser.rb:95:in `parse'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/streamparser.rb:79:in `parse'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:75:in `block in start'
W, [2012-07-02T11:28:55.044019 #13000]  WARN -- : EXCEPTION:
    IOError
    stream closed
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `write'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `<<'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `block in send_data'
    <internal:prelude>:10:in `synchronize'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:344:in `send_data'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:378:in `send'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:88:in `start'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/connection.rb:173:in `starttls'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/connection.rb:109:in `accept_features'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/connection.rb:79:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:70:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:57:in `block in connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:55:in `each'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:55:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/lib/robut/connection.rb:118:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/bin/robut:9:in `<top (required)>'
    G:/Ruby193/bin/robut:23:in `load'
    G:/Ruby193/bin/robut:23:in `<main>'
W, [2012-07-02T11:28:55.046019 #13000]  WARN -- : Exception caught while sending! (IOError)
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `write'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `<<'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `block in send_data'
    <internal:prelude>:10:in `synchronize'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:344:in `send_data'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:378:in `send'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:88:in `start'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/connection.rb:173:in `starttls'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/connection.rb:109:in `accept_features'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/connection.rb:79:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:70:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:57:in `block in connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:55:in `each'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:55:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/lib/robut/connection.rb:118:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/bin/robut:9:in `<top (required)>'
    G:/Ruby193/bin/robut:23:in `load'
    G:/Ruby193/bin/robut:23:in `<main>'
D, [2012-07-02T11:28:55.048019 #13000] DEBUG -- : STARTTLS:
    Failure: stream closed
D, [2012-07-02T11:28:55.049019 #13000] DEBUG -- : SENDING:
    <iq id='1189' type='set' xmlns='jabber:client'><query xmlns='jabber:iq:auth'><username>xxx</username><diges
t>7231e1ecba661b473fee5ac3df2b504bd456e513</digest><resource>bot</resource></query></iq>
W, [2012-07-02T11:28:55.050019 #13000]  WARN -- : EXCEPTION:
    IOError
    closed stream
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `write'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `<<'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `block in send_data'
    <internal:prelude>:10:in `synchronize'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:344:in `send_data'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:375:in `send'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:432:in `send_with_id'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:241:in `auth_nonsasl'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:114:in `auth'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/lib/robut/connection.rb:119:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/bin/robut:9:in `<top (required)>'
    G:/Ruby193/bin/robut:23:in `load'
    G:/Ruby193/bin/robut:23:in `<main>'
W, [2012-07-02T11:28:55.051020 #13000]  WARN -- : Exception caught while sending! (IOError)
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `write'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `<<'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `block in send_data'
    <internal:prelude>:10:in `synchronize'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:344:in `send_data'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:375:in `send'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:432:in `send_with_id'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:241:in `auth_nonsasl'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:114:in `auth'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/lib/robut/connection.rb:119:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/bin/robut:9:in `<top (required)>'
    G:/Ruby193/bin/robut:23:in `load'
    G:/Ruby193/bin/robut:23:in `<main>'
D, [2012-07-02T11:28:55.053020 #13000] DEBUG -- : IOError: closed stream
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `write'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `<<'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:346:in `block in send_data'
    <internal:prelude>:10:in `synchronize'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:344:in `send_data'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:375:in `send'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/stream.rb:432:in `send_with_id'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:241:in `auth_nonsasl'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:114:in `auth'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/lib/robut/connection.rb:119:in `connect'
    G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/bin/robut:9:in `<top (required)>'
    G:/Ruby193/bin/robut:23:in `load'
    G:/Ruby193/bin/robut:23:in `<main>'
G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:118:in `rescue in auth': closed stream (Jabber::Clie
ntAuthenticationFailure)
        from G:/Ruby193/lib/ruby/gems/1.9.1/gems/xmpp4r-0.5/lib/xmpp4r/client.rb:108:in `auth'
        from G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/lib/robut/connection.rb:119:in `connect'
        from G:/Ruby193/lib/ruby/gems/1.9.1/gems/robut-0.3.0/bin/robut:9:in `<top (required)>'
        from G:/Ruby193/bin/robut:23:in `load'
        from G:/Ruby193/bin/robut:23:in `<main>'

Plugin activity on Robut startup...

I'm pretty sure I know the answer already but I'm curious if anyone else is looking to do this, or if there's a work around. I've hacked together a cron job plugin - and I want to persist cron jobs via the store['jobs'] facility, which I can do no problem. But, what I'm really looking to do now, is have the plugin restore those jobs on a Robut restart - reading them from the file and resubmitting the jobs to rufus-scheduler. Any ideas on how to "initialize" stuff in Plugin-land when Robut starts?

restrict to only room not individual chat

I set up robut and it works great.
Is there any way I can restrict the chat only to a room?
Basically people can use the bot only from the room and not chat against the bot individually.

Add alarm clock plugin

Something like this:

@robut in 5 minutes message me

(5 minutes later)

@ben times up!

Not sure on the best syntax.

It might also be cool for modifiers like "in 5 minutes" to perform whatever comes next as it normally would, just 5 minutes later.

private server old message woes

On the private hipchat server for some terrible reason, all bots get huge swatches of history when they join, which leads to bots repeating themselves over and over when the dyno cycles each day, until there is enough traffic in the room to push that out of whatever the history period is. For whatever reason this isn't a problem on the public server.

One way I've thought to fix this is have robut only respond if the timestamp of the incoming message is 'recent enough', but I'm not sure if that'll work, which is why I asked first when I saw a random tweet of yours and was reminded of this whole situation.

On twitter you asked me if I'm "using the /bot resource" but I'm not really sure what that is, so I don't know. What is that?

Specify chat.hipchat.com explicitly when connecting to server

If we don't specify the server explicitly, the underlying xmpp4r library will perform a DNS lookup on _xmpp-client._tcp.chat.hipchat.com, which, as of late doesn't seem to exist. Worse yet, there is no timeout associated with the DNS lookup, so the process will just hang if it can't resolve with a DNS server.

We can avoid the DNS lookup altogether simply by specifying the server to connect to. Patch forthcoming...

Reconnect on failures

From the xmpp4r docs:

If you want your connection to survive disconnects and timeouts, catch exception in Stream#on_exception and re-call Client#connect and Client#auth. Don‘t forget to re-send initial Presence and everything else you need to setup your session.

Routing, Transforming and Action DSL

Working with Robut reminds me of all the hours I put into Cucumber. In a similar way a plugin defines criteria for matching incoming messages (similar to a step definition). Then when the message is matched to a particular regex I transform the parameters found within the message to the types/objects I need (similar to a step transform).

So I was toying around with the idea of some sort of DSL that would stream-line these operations but wanted to get some feedback.

register_route :play,
  :sent_only_to_me,
  :usage => "#{at_nick} play <track number> - queues <track number> from results for playing",
  :match => /^(?:play)?\s?((?:\d[\s,-]*)+)$/,
  :transform => lambda {|track_request|
    Array(track_request).join(' ')[play_results_regex,-1].to_s.split(/(?:\s|,\s?)/).map do |track| 
      tracks = track.split("-")
      (tracks.first.to_i..tracks.last.to_i).to_a
    end.flatten
  }

route_to_action :play => :play_result

def play_result(track_numbers)
  time # => would return the time of the message
  sender # => would return who sent the message
  message # => would return the original message
  # do some queuing and playing...
end

So a developer could:

  1. Create / Register Routes
  2. Tie routes to a method or methods that they would execute

Weather Plugin

Since the Google Weather API has been gone for quite awhile now, I've recently begun work on a Wunderground based replacement. My question is, if I want to submit it back, would you prefer it be a separate plugin module like you have some of them now, or would you want a fork and pull request to simply update the existing one?

Trying to figure out how to get robut to join rooms when invited

I'd like to have the bot appear in rooms when you @ mention it.

I've figured out how to notice the invite, but joining the room after Connection.new.connect doesn't seem to work

Invitaitons look like

 <message from='(room name)@conf.hipchat.com' to='(id)@chat.hipchat.com'><x xmlns='http://jabber.org/protocol/muc#user'><invite from='(id)@chat.hipchat.com/osx'><reason>@DumboTBot some message</reason></invite></x><x xmlns='http://hipchat.com/protocol/muc#room'><name>room name</name><topic>The topic of the room</topic><privacy>public</privacy></x></message>

Notably the message does not have a type.

I was able to just quick hack into the PM class to print something when invited:

class Robut::PM < Robut::Presence
  def initialize(connection, rooms)
    # Add the callback from direct messages. Turns out the
    # on_private_message callback doesn't do what it sounds like, so I
    # have to go a little deeper into xmpp4r to get this working.
    self.connection = connection
    connection.client.add_message_callback(200, self) do |message|
      invited(message, connection)
     # ... rest of that method
  end

  def invited(message, conn)
    if message.type.nil?
      p message.to_s
      if message.to_s =~ /invite/ # because I didn't want to figure out how to traverse to see the <invite> just to see if this worked at all
        begin
          room_name = "#{message.from.node}@conf.hipchat.com"
          puts "joining #{room_name}"

        room = Robut::Room.new(conn, message.from.node + '@conf.hiphcat.com')
        room.join
        room.reply("I am here", nil)

        rescue => e
         p e
        end
      end
    end         

The Room.new and the #join don't raise exceptions, but the bot never joins the room.
Any ideas how to do this?

'initialize': uninitialized constant Robut::Storage::HashStore on initialization

When trying to start up my bot with: "robut Chatfile" I am getting the following error:

vagrant@tricenix:~/app$ robut Chatfile
/usr/local/rvm/gems/ruby-2.1.2/gems/robut-0.5.2/lib/robut/connection.rb:68:in `initialize': uninitialized constant Robut::Storage::HashStore (NameError)
    from /usr/local/rvm/gems/ruby-2.1.2/gems/robut-0.5.2/bin/robut:14:in `new'
    from /usr/local/rvm/gems/ruby-2.1.2/gems/robut-0.5.2/bin/robut:14:in `<top (required)>'
    from /usr/local/rvm/gems/ruby-2.1.2/bin/robut:23:in `load'
    from /usr/local/rvm/gems/ruby-2.1.2/bin/robut:23:in `<main>'
    from /usr/local/rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `eval'
    from /usr/local/rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `<main>'

Here is my Chatfile:

require 'robut/plugin/sayings'

Robut::Plugin.plugins << Robut::Plugin::Sayings

Robut::Connection.configure do |config|
  config.jid = "[email protected]/bot"
  config.password = "$BOT_ACCOUNT_PASSWORD"
  config.nick = "Bot Nickname"
  config.room = "[email protected]"
  config.mention_name = "botnickname"
  config.enable_private_messaging = false
  config.logger = Logger.new(STDOUT)
end

and my config.ru

require 'rubygems'
require 'bundler/setup'
Bundler.require :default

require 'robut'
require 'ostruct'
require 'logger'

load './Chatfile'

Robut::Web.set :connection, Robut::Connection.new.connect

run Robut::Web

I have tried leaving the config.password as a blank string as I don't know if it is the room's password or the bot account's password. But nowhere in the documentation does it say a bot account needs to be set up? Kind of confusing.

@robut never responds?

ruby 1.9.3-p194. I have installed robut using "gem install robut" and am using the config (minus pw) shown below.

My robut successfully logs in (I can see it online in the client as another user) and I can see it reading all the messages, but it never replies. Thoughts?

require 'robut/plugin/calc' 
require 'robut/storage/yaml_store'  
require 'robut/plugin/ping' 

Robut::Plugin.plugins << Robut::Plugin::Calc  
Robut::Plugin.plugins << Robut::Plugin::Ping

Robut::Connection.configure do |config|   
  config.jid = '***@chat.hipchat.com/bot'   
  config.password = '*********'   
  config.nick = '***'
  config.room = '***@conf.hipchat.com'    

  # Example of the YamlStore which uses a yaml file for persistence   
  Robut::Storage::YamlStore.file = "~/.robut_store"   
  config.store = Robut::Storage::YamlStore    

  # Add a logger if you want to debug the connection   
  config.logger = Logger.new(STDOUT) 

end

TIA!

Robut spams the room on entering.

I'm using robut 0.3.0 with the following Chatfile (information filtered to protect secrets):

# Require your plugins here
require 'robut/storage/yaml_store'

require 'robut/plugin/help'
Robut::Plugin.plugins << Robut::Plugin::Help

# Configure the robut jabber connection and you're good to go!
Robut::Connection.configure do |config|
  config.jid = '[email protected]'
  config.password = '...'
  config.nick = 'Carebot Machine'
  config.room = '[email protected]'

  # Some plugins require storage
  Robut::Storage::YamlStore.file = ".robut"
  config.store = Robut::Storage::YamlStore

  # Add a logger if you want to debug the connection
  # config.logger = Logger.new(STDOUT)
end

Just the help plugin, as you can see. However, when Carebot joins the room:

Supported commands:
@carebot help - displays this message
@carebot help - displays this message
Supported commands:
Supported commands:
@carebot help - displays this message

or thereabouts. The actual number of messages varies, but it's always more than one and interleaved. It seems to me that Robut should, on entering a room, either:

  • be silent or
  • display the contents of 'help' but once.

Plugin fetching data periodically

I have ruby script, which runs as daemon and fetches some data from internet every 60 seconds, and posts messages in our channel using HipChat's url hook.
I want to move this logic into robut plugin, but all plugins in samples triggered by messages. Can you please provide sample, which will post any message into channel every N seconds starting from robut launch?

no response

Hi, I have set-up robut work with hipchat. It looks fun. But i found it did not response my message. If I use a guess or another account to join the chat room. it works.
Is it possible to ask robut response to my message.

Feature: Fork process into background

Perhaps there's already a way to do this and I'm completely missing it, but I'd like to request a way to fork the process into the background. My goal is to put the bot in upstart or equivalent. Server hiccups cause him to disconnect, and seeing the process die would be helpful.

Join multiple MUC rooms.

This will likely require a major change, but I would love the ability to connect to multiple rooms, but not all of them.

For instance, we have a room for developer talk - and that would be a nice place to issue Robut commands for kicking servers, deploying code, etc. However, we'd also like him in our general banter room so he can answer questions, suggest lunch joints, etc.

The biggest issue now is that the current implementation often assumes only one Muc, and defaults to it in certain cases. We may want to consider a design where we can spin up multiple Mucs, and each listens for its own messages, delegating work to plugins, and providing itself as the object that knows how to reply to that room.

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.