• Stars
    star
    119
  • Rank 297,930 (Top 6 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 13 years ago
  • Updated over 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A framework for writing Campfire bots.

Build Status

Scamp

A framework for writing Campfire bots. Scamp is in early development so use it at your own risk, pull requests welcome.

Scamp is designed to be simple, to get out of your way and to let you do what you want. It doesn't have any baggage, so no administration web interfaces, no built in commands. It's a blank slate for you to build on.

If you like or use Scamp I'd love to hear from you. Drop me at line at will at 37signals dot com and tell me how you are using it.

Requirements

Ruby >= 1.9.2 (At least for the named captures)

Installation

gem install scamp or put gem 'scamp' in your Gemfile.

Usage and Examples

The most simple example:

require 'scamp'

scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :verbose => true)

scamp.behaviour do
  # Simple matching based on regex or string:
  match "ping" do
    say "pong"
  end
end

# Connect and join some rooms
scamp.connect!([293788, "Monitoring"])

Everyone wants an image search

require 'scamp'
require 'cgi'

scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :verbose => true)

scamp.behaviour do
  match /^artme (?<search>\w+)/ do
    url = "http://ajax.googleapis.com/ajax/services/search/images?rsz=large&start=0&v=1.0&q=#{CGI.escape(search)}"
    http = EventMachine::HttpRequest.new(url).get
    http.errback { say "Couldn't get #{url}: #{http.response_status.inspect}" }
    http.callback {
      if http.response_header.status == 200
        results = Yajl::Parser.parse(http.response)
        if results['responseData']['results'].size > 0
          say results['responseData']['results'][0]['url']
        else
          say "No images matched #{search}"
        end
      else
        # logger.warn "Couldn't get #{url}"
        say "Couldn't get #{url}"
      end
    }
  end
end

# Connect and join some rooms
scamp.connect!([293788, "Monitoring"])

A more in-depth run through

Matchers are tested in order and all that satisfy the match and conditions will be run. Careful, Scamp listens to itself, you could easily create an infinite loop. Look in the examples dir for more.

require 'scamp'

# Add :verbose => true to get debug output, otherwise the logger will output INFO
scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :verbose => true)

scamp.behaviour do
  # 
  # Simple matching based on regex or string:
  # 
  match /^repeat (\w+), (\w+)$/ do
    say "You said #{matches[0]} and #{matches[1]}"
  end

  #
  # You can specifically paste text: 
  #
  
  match "paste stuff" do
    paste "Awesome texts"
    
    # say()'ing multiline strings will paste automatically however:
    say <<-EOS
This will be pasted
even though you called say
    EOS
  end
  
  # 
  # A special user and room method is available in match blocks.
  # 
  match "a user said" do
    say "#{user} said something in room #{room}"
  end
  
  match "Hello!" do
    say "Hi there"
  end
  
  # 
  # You can play awesome sounds
  # 
  match "ohmy" do
    play "yeah"
  end
  
  # 
  # Limit the match to certain rooms, users or both.
  # 
  match /^Lets match (.+)$/, :conditions => {:room => "Some Room"} do
    say "Only said if room name matches 'Some Room'"
  end
  
  match "some text", :conditions => {:user => "Some User"} do
    say "Only said if user name matches 'Some User'"
  end
  
  match /some other text/, :conditions => {:user => "Some User", :room => 123456} do
    say "You can mix conditions"
  end

  match "some text", :conditions => {:room => ["Some Room", "Some Other Room"]} do
    say "You can list multiple rooms"
  end

  # 
  # Named captures become available in your match block
  # 
  match /^say (?<yousaid>.+)$/ do
    say "You said #{yousaid}"
  end
  
  # 
  # You can say multiple times, and you can specify an alternate room.
  # Default behaviour is to 'say' in the room that caused the match.
  # 
  match "something" do
    say "#{user} said something in room #{room}"
    say "#{user} said something in room #{room}", 237872
    say "#{user} said something in room #{room}", "System Administration"
  end
  
  # 
  # A list of commands is available as command_list this matcher uses it
  # to format a help text
  # 
  match "help" do
    max_command_length = command_list.map{|cl| cl.first.to_s }.max_by(&:size).size
    format_string = "%#{max_command_length + 1}s"
    formatted_commands = command_list.map{|action, conds| "#{sprintf(format_string, action)} | #{conds.size == 0 ? '' : conds.inspect}"}
    say <<-EOS
#{sprintf("%-#{max_command_length + 1}s", "Command match")} | Conditions
--------------------------------------------------------------------------------
#{formatted_commands.join("\n")}
    EOS
  end
end
  
# Connect and join some rooms
scamp.connect!([293788, "Monitoring"])

In the room/user conditions and say/play commands you can use the name or ID of a user or room, eg:

:conditions => {:room => "some string"}
:conditions => {:room => 123456}

:conditions => {:user => "some string"}
:conditions => {:user => 123456}

say "#{user} said something in room #{room}", 237872
say "#{user} said something in room #{room}", "System Administration"

By default Scamp listens to itself. This could either be fun, or dangerous, you decide. You can turn this off by passing :ignore_self => true in the initialisation options:

scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :ignore_self => true)

Scamp will also run all match blocks that an input string matches, you can make Scamp only run the first block it matches by passing in :first_match_only => true:

scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :first_match_only => true)

Scamp will listen to all messages that are sent on the rooms it is listening on and doesn't need to be addressed by name. If you prefer to only trigger bot commands when you address your bot directly add the :required_prefix initialisation option:

scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain", :required_prefix => 'Bot: ')

Scamp will now require commands to begin with 'Bot: ' (or whatever you have specified), and will strip out this prefix before handing the message onto your match block.

TODO

* Allow multiple values for conditions, eg: :conditions => {:user => ["Some User", "Some Other User"]}

How to contribute

Here's the most direct way to get your work merged into the project:

  1. Fork the project
  2. Clone down your fork
  3. Create a feature branch
  4. Add your feature + tests
  5. Document new features in the README
  6. Make sure everything still passes by running the tests
  7. If necessary, rebase your commits into logical chunks, without errors
  8. Push the branch up
  9. Send a pull request for your branch

Take a look at the TODO list or known issues for some inspiration if you need it.

Authors

Thanks

First class support, commits and pull requests, thanks guys!

License

See LICENSE.md

More Repositories

1

build_ruby

Go program for building Ruby packages using Docker
Go
36
star
2

gamepad

Pull values from gamepads over USB
C
23
star
3

typo_safe

Protect your Ruby code from typos
Ruby
18
star
4

rolling_timeout

A timeout class with a rolling timeout window
Ruby
14
star
5

Rugbot

NWRUG IRC helper bot
Ruby
14
star
6

go-piglow

Go lib for making the Piglow do stuff
Go
13
star
7

rpi_video_tools

Go programs for doing stuff with the camera module
Go
6
star
8

em-campfire

EventMachine API wrapper for Campfire
Ruby
5
star
9

eymigrate

eymigrate
Ruby
4
star
10

asset-format

Plugin to add an asset id into the path of the asset instead of appending it to the end with a question mark
Ruby
4
star
11

lcm1602_lcd

Go driver for the LCM1602 LCD
Go
3
star
12

rpi_go_bme280_example

Example code for reading and logging sensor data from a BME280
Go
3
star
13

httperf-output-parser

Library for parsing the output of httperf into Ruby
Ruby
3
star
14

yahoo-group-data

Ruby lib for fetching public Yahoo group data
Ruby
2
star
15

oas_agent

The Own & Ship Ruby agent
Ruby
2
star
16

mango.computer

The Mango website
HTML
2
star
17

motorpitx_power_control

Power control for the MotorPiTX using the power button
Go
2
star
18

statsd_stresser

Tool for sending a lot of data to a statsd implementation
Go
1
star
19

wordpress_to_hugo

A small program for converting a wordpress XML dump to Hugo files, including images.
Go
1
star
20

silvergirl_website

The website of the Sailing yacht Silver Girl
SCSS
1
star
21

teesectionreader

A Go sectionreader that writes all data read to the provided writer
Go
1
star
22

passthroughdigest

A Go IO object that calculates the MD5 hash of any data written through it
Go
1
star
23

sectionwriter

SectionWriter allows for creating windows into a file for writing, much the same as the SectionReader in the standard library
Go
1
star