hipchat_bot 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Grant Ammons
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # HipchatBot
2
+
3
+ Simple and configurable bot for Hipchat!
4
+
5
+ Obviously adapted from https://github.com/gammons/happy_fun_time_bot, but revised with a new shorter name and
6
+ to work on Ruby 1.9.3 since the original is broken.
7
+
8
+ 100% of the credit to https://github.com/gammons/happy_fun_time_bot
9
+ and [gammons](https://github.com/gammons) for this gem. I just made it work on 1.9.3
10
+
11
+ Lets take a look!
12
+
13
+ ```ruby
14
+ #!/usr/bin/env ruby
15
+
16
+ require 'rubygems'
17
+ require 'hipchat_bot'
18
+
19
+ @bot = HipchatBot.new(:jid => "xxxx@chat.hipchat.com",
20
+ :nick => "Hipchat Bot",
21
+ :room => "123_your_talk_chan@conf.hipchat.com",
22
+ :password => "xxxx")
23
+
24
+ @bot.add_responder('heybot') do |from, args|
25
+ "Oh HAI #{from}!!!"
26
+ end
27
+
28
+ @bot.run!
29
+ ```
30
+
31
+ ```
32
+ Bob: !heybot what's up?
33
+ HipChat Bot: Oh HAI Bob!!!
34
+ ```
35
+
36
+ ### So many IdeazzZz!!
37
+
38
+ **Add responders to insert random images of dogs in costumes!**
39
+
40
+ ```
41
+ Bob: !findimage dog costume
42
+ HipChat Bot: Here ya go!
43
+ ```
44
+ ![](http://spoilurpets.com/images/Lobster%20Paws%20Dog%20Costume.JPG)
45
+
46
+
47
+ **Kick off a build!**
48
+
49
+ ```
50
+ Bob: !build_the_app
51
+ HipChat Bot: All tests PASSED!
52
+ ```
53
+
54
+ ![](http://thehairpin.com/wp-content/uploads/2010/12/womanpic1001_228x342.jpeg)
55
+
56
+ **Deploy your app!**
57
+
58
+ ```
59
+ Bob: !deploy
60
+ HipChat Bot: Deploying now!
61
+ ```
62
+
63
+ ### Bot creation Options:
64
+
65
+ * `:jid` - Required.
66
+ * `:nick` - The nickname for the bot to use.
67
+ * `:room` - Required. The room to enter.
68
+ * `:password` - The bot's password.
69
+ * `:command_regex` - The regular expression to test for a command. The default is a ! followed by a word. e.g. `/^!(.+)$/`
70
+
71
+ ## Copyright
72
+
73
+ Copyright (c) 2012 Nathan Esquenazi. See LICENSE.txt for further details.
74
+ Copyright (c) 2011 Grant Ammons. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'hipchat_bot'
5
+
6
+ # For hipchat, your :jid, :room and :password are available at https://www.hipchat.com/account/xmpp
7
+ @bot = HipchatBot.new(:jid => "xxxxx@chat.hipchat.com", :nick => "ImageBot", :room => "your_room@conf.hipchat.com", :password => "xxx")
8
+
9
+ # calling !heybot will return a simple response.
10
+ @bot.add_responder('heybot') do |from, args|
11
+ "Hai, #{from}!!"
12
+ end
13
+
14
+ # endless loop. Use bluepill or something else to daemonize it.
15
+ @bot.run!
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ %w(rubygems hipchat_bot httparty).each {|r| require r }
3
+
4
+ # For hipchat, your :jid, :room and :password are available at https://www.hipchat.com/account/xmpp
5
+ @bot = HipchatBot.new(:jid => "xxxxx@chat.hipchat.com", :nick => "ImageBot", :room => "your_room@conf.hipchat.com", :password => "xxx")
6
+
7
+ # Let's create a simple image getter from google.
8
+ class Google
9
+ include HTTParty
10
+ format :json
11
+
12
+ def self.get_image_url(search, options = {:start => 0})
13
+ if options[:random]
14
+ options[:start] = rand(12)
15
+ end
16
+
17
+ res = Google.get("https://ajax.googleapis.com/ajax/services/search/images?v=1.0&safe=active&start=#{options[:start]}&rsz=8&q=#{URI.escape(search)}")
18
+ res["responseData"]["results"][0]["url"]
19
+ end
20
+
21
+ def self.get_youtube_url(search)
22
+ res = Google.get("http://gdata.youtube.com/feeds/api/videos?q=#{URI.escape(args)}&alt=json")
23
+ res["feed"]["entry"][0]["link"][0]['href']
24
+ end
25
+ end
26
+
27
+
28
+ # let's find some images!
29
+ @bot.add_responder('findimage') do |from, args|
30
+ url = Google.get_image_url(args)
31
+ "Look! #{url}"
32
+ end
33
+
34
+ @bot.run!
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/hipchat_bot/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Nathan Esquenazi"]
6
+ gem.email = ["nesquena@gmail.com"]
7
+ gem.description = %q{Easily create hipchat bots that can respond to anything!}
8
+ gem.summary = %q{Simple XMPP bot framework}
9
+ gem.homepage = %q{http://github.com/bazaarlabs/hipchat_bot}
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "hipchat_bot"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = HipchatBot::VERSION
17
+
18
+ gem.add_runtime_dependency('xmpp4r', ">= 0")
19
+ gem.add_runtime_dependency('json', ">= 0")
20
+ gem.add_runtime_dependency('httparty', ">= 0")
21
+ gem.add_development_dependency('rspec', "~> 2")
22
+ gem.add_development_dependency('yard', "~> 0.6.0")
23
+ gem.add_development_dependency('bundler', "~> 1")
24
+ end
@@ -0,0 +1,67 @@
1
+ require "hipchat_bot/version"
2
+ require 'rubygems'
3
+ require 'xmpp4r'
4
+ require 'xmpp4r/muc/helper/simplemucclient'
5
+ require 'open-uri'
6
+ require 'cgi'
7
+
8
+ $: << File.expand_path(File.dirname(__FILE__))
9
+
10
+ require 'responder'
11
+ require 'hipchat_bot/muc_client'
12
+
13
+ class HipchatBot
14
+ attr_accessor :config, :client, :muc, :responders, :command_regexp
15
+
16
+ def initialize(config = {})
17
+ config = {:command_regex => /^!(.+)$/}.merge(config)
18
+ self.client = Jabber::Client.new(config[:jid])
19
+ self.muc = Jabber::MUC::SimpleMUCClient.new(client)
20
+ self.command_regexp = /^!(.+)$/
21
+ self.responders = []
22
+ self.config = config
23
+
24
+ Jabber.debug = true if Jabber.logger = config[:debug]
25
+ self
26
+ end
27
+
28
+ def connect
29
+ client.connect
30
+ client.auth(self.config[:password])
31
+ client.send(Jabber::Presence.new.set_type(:available))
32
+
33
+ salutation = config[:nick].split(/\s+/).first
34
+
35
+ muc.on_message { |time, nick, text| process(nick, text) }
36
+
37
+ muc.join(self.config[:room] + '/' + self.config[:nick])
38
+ self
39
+ end
40
+
41
+ def add_responder(command = nil, &block)
42
+ responders << Responder.new(command, &block)
43
+ end
44
+
45
+ def run!
46
+ connect
47
+ loop { sleep 1 }
48
+ end
49
+
50
+ private
51
+
52
+ def process(from, command)
53
+ return [] if !responders.any? {|r| r.command.nil? } and !(command =~ self.config[:command_regex])
54
+
55
+ responders.select {|r| r.responds_to?($1) }.map do |responder|
56
+ args = command.split
57
+ args.shift
58
+ ret = responder.block.call(from, args.join(' '))
59
+ send_response(ret)
60
+ ret
61
+ end
62
+ end
63
+
64
+ def send_response(msg)
65
+ muc.send Jabber::Message.new(muc.room, msg)
66
+ end
67
+ end
@@ -0,0 +1,65 @@
1
+ # We want the MUC functionality to just handle shit for us. Unfortunately we
2
+ # have to override/repeat the join method in order to add the directive that
3
+ # will disable the history being sent to us. :-(
4
+ module Jabber
5
+ module MUC
6
+ class MUCClient
7
+
8
+ def join(jid, password=nil)
9
+ if active?
10
+ raise "MUCClient already active"
11
+ end
12
+
13
+ @jid = (jid.kind_of?(JID) ? jid : JID.new(jid))
14
+ activate
15
+
16
+ # Joining
17
+ pres = Presence.new
18
+ pres.to = @jid
19
+ pres.from = @my_jid
20
+ xmuc = XMUC.new
21
+ xmuc.password = password
22
+ pres.add(xmuc)
23
+
24
+ # NOTE: Adding 'maxstanzas="0"' to 'history' subelement of xmuc nixes
25
+ # the history being sent to us when we join.
26
+ history = XMPPElement.new('history')
27
+ history.add_attributes({'maxstanzas' => '0'})
28
+ xmuc.add(history)
29
+
30
+ # We don't use Stream#send_with_id here as it's unknown
31
+ # if the MUC component *always* uses our stanza id.
32
+ error = nil
33
+ @stream.send(pres) { |r|
34
+ if from_room?(r.from) and r.kind_of?(Presence) and r.type == :error
35
+ # Error from room
36
+ error = r.error
37
+ true
38
+ # type='unavailable' may occur when the MUC kills our previous instance,
39
+ # but all join-failures should be type='error'
40
+ elsif r.from == jid and r.kind_of?(Presence) and r.type != :unavailable
41
+ # Our own presence reflected back - success
42
+ if r.x(XMUCUser) and (i = r.x(XMUCUser).items.first)
43
+ @affiliation = i.affiliation # we're interested in if it's :owner
44
+ @role = i.role # :moderator ?
45
+ end
46
+
47
+ handle_presence(r, false)
48
+ true
49
+ else
50
+ # Everything else
51
+ false
52
+ end
53
+ }
54
+
55
+ if error
56
+ deactivate
57
+ raise ServerError.new(error)
58
+ end
59
+
60
+ self
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ class HipchatBot
2
+ VERSION = "0.1.0"
3
+ end
data/lib/responder.rb ADDED
@@ -0,0 +1,17 @@
1
+ class Responder
2
+ attr_accessor :command, :block
3
+
4
+ def initialize(command, &block)
5
+ @command = command
6
+ @block = block
7
+ end
8
+
9
+ def responds_to?(command)
10
+ # respond to all if our command is nil.
11
+ return true if @command.nil?
12
+
13
+ # otherwise parse out the command and make sure it matches
14
+ # our command.
15
+ @command == command.split.first
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "HipchatBot" do
4
+ it "should load everything properly" do
5
+ HipchatBot
6
+ lambda { HipchatBot.new }.should_not raise_error
7
+ end
8
+
9
+ describe "commands" do
10
+ it "should have a configurable command regex" do
11
+ @bot = HipchatBot.new(:command_regex => /^#(.+)$/)
12
+ @bot.stub(:send_response)
13
+ @bot.add_responder("findimage") { |from, args| "finding an image" }
14
+ @bot.send(:process, "bob", "#findimage monkey").should == ["finding an image"]
15
+ @bot.send(:process, "bob", "!findimage monkey").should == []
16
+ end
17
+ end
18
+
19
+ describe "responding" do
20
+ before(:each) do
21
+ @bot = HipchatBot.new
22
+ @bot.stub(:send_response)
23
+ end
24
+
25
+ it "should respond if there is a responder" do
26
+ @bot.add_responder("findimage") { |from, args| "finding an image" }
27
+ @bot.send(:process, "bob", "!findimage monkey").should == ["finding an image"]
28
+ end
29
+
30
+ it "should have multiple responses" do
31
+ @bot.add_responder("findimage") { |from, args| "finding an image" }
32
+ @bot.add_responder("google") { |from, args| "googling for you, #{from}." }
33
+
34
+ @bot.send(:process, "bob", "!findimage monkey").should == ["finding an image"]
35
+ @bot.send(:process, "bob", "!google monkey").should == ["googling for you, bob."]
36
+ end
37
+
38
+ it "should contain the args in the args arg" do
39
+ @bot.add_responder("argarg") { |from, args| "your args are #{args}" }
40
+ @bot.send(:process, "bob", "!argarg monkey costume").should == ["your args are monkey costume"]
41
+ end
42
+
43
+ it "should respond to all messages if we did not specify a specific responder" do
44
+ @bot.add_responder { |from, args| "got it." }
45
+ @bot.send(:process, "jim", "sending some stuff").should == ["got it."]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'hipchat_bot'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hipchat_bot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nathan Esquenazi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: xmpp4r
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: httparty
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '2'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2'
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.6.0
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.6.0
94
+ - !ruby/object:Gem::Dependency
95
+ name: bundler
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '1'
110
+ description: Easily create hipchat bots that can respond to anything!
111
+ email:
112
+ - nesquena@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - Gemfile
119
+ - LICENSE.txt
120
+ - README.md
121
+ - Rakefile
122
+ - VERSION
123
+ - examples/example.rb
124
+ - examples/find_image.rb
125
+ - hipchat_bot.gemspec
126
+ - lib/hipchat_bot.rb
127
+ - lib/hipchat_bot/muc_client.rb
128
+ - lib/hipchat_bot/version.rb
129
+ - lib/responder.rb
130
+ - spec/hip_chat_spec.rb
131
+ - spec/spec_helper.rb
132
+ homepage: http://github.com/bazaarlabs/hipchat_bot
133
+ licenses: []
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: Simple XMPP bot framework
156
+ test_files:
157
+ - spec/hip_chat_spec.rb
158
+ - spec/spec_helper.rb