Skip to content

Instantly share code, notes, and snippets.

@beccasaurus
Created December 14, 2009 09:07
Show Gist options
  • Save beccasaurus/255919 to your computer and use it in GitHub Desktop.
Save beccasaurus/255919 to your computer and use it in GitHub Desktop.

Not Vark.com

Prototype for asking questions on a site, having it go out to an external messaging system, and getting the responses back to the user who asked the question.

Video demo: www.viddler.com/explore/remitaylor/videos/32/

NOTE: This isn’t 100% working, as Jabber::Simple doesn’t like to support multiple connections to the same GTalk server. If the code were ported to use xmpp4r, it should work fine.

This uses GTalk as the externam messaging system.

Usage

Run notvark.rb (Sinatra application) and be sure to set the following environment variables:

USER

the GTalk bot username

PASS

the password for the GTalk bot

HOST

the path to the web server, eg. localhost:4567/

To set the recipients (the people who will be IM’d when a question is submitted), edit notvark.rb.

When you submit a question, you should receive an IM, eg.

“Q5: What is your favorite color?”

To reply with an answer, reply with something like:

“A5: Blue”

The A needs to match the Q.

For questions to be processed, you need to be running the answer_daemon.rb in the background.

Installation and Running

sudo gem install shotgun sinatra haml xmpp4r-simple httparty # and the datamapper gems

shotgun config.ru
#! /usr/bin/env ruby
require File.dirname(__FILE__) + '/notvark'
system "clear"
puts "Answer Daemon"
TheGTalkBot.listen_for_answers
require File.dirname(__FILE__) + '/notvark'
dev_db = "sqlite3://#{ File.expand_path(File.dirname(__FILE__) + 'notvark.sqlite3') }"
DataMapper.setup :default, ENV['DATABASE_URL'] || dev_db
DataMapper.auto_upgrade!
run Sinatra::Application
%w( rubygems sinatra haml xmpp4r-simple httparty
dm-core dm-validations dm-timestamps dm-aggregates ).each {|lib| require lib }
# GTalk bot that:
# - can IM posted questions to a list of GTalk users
# - can sit and watch GTalk for answers to questions
class GTalkBot
attr_accessor :recipients
def initialize username, password, host
raise "You need to specify USER and PASS environment variables to initialize GTalk Bot" unless username and password
raise "You need to specify a HOST that we will use to make requests to the Web API" unless host
@messenger = Jabber::Simple.new username, password
@host = host
end
def listen_for_answers
while true
@messenger.received_messages do |msg| # .from, .body
if msg.body =~ /[aA](\d+):(.*)/
begin
question_id = $1
answer = $2.strip
HTTParty.post File.join(@host, "/#{ question_id }"), :body => { :answer => answer }
puts "Posted answer for question #{ question_id }: #{ answer }"
rescue Exception => ex
puts "Something blew up: #{ ex.inspect }"
end
else
puts "don't know how to respond to message: #{ msg.inspect }"
end
end
sleep 2
end
end
def send_question question
recipients.each do |recipient|
@messenger.deliver recipient, "Q#{ question.id }: #{ question.text }"
end
end
end
# initialize bot
TheGTalkBot = GTalkBot.new ENV['USER'], ENV['PASS'], ENV['HOST']
TheGTalkBot.recipients = ['YOUR-ACCOUNT@gmail.com']
# Represents a question that has been asked.
# Once created, it tells the GTalk bot to IM this question to everyone.
class Question
include DataMapper::Resource
property :id, Serial
property :text, Text, :nullable => false, :lazy => false
has n, :answers
after :create, :send_to_gtalk
def send_to_gtalk
TheGTalkBot.send_question self
end
end
# Represents an answer to a Question.
class Answer
include DataMapper::Resource
property :id, Serial
property :question_id, Integer, :nullable => false
property :text, Text, :nullable => false, :lazy => false
belongs_to :question
end
# Home page. Allows you to create questions!
get '/' do
haml :index
end
# Make a new question.
post '/' do
@question = Question.create :text => params[:question]
redirect "/#{ @question.id }"
end
get '/add_recipient/:email' do
TheGTalkBot.recipients << params[:email]
"Added #{ params[:email] } to recipient list for questions"
end
# Get the status of a question.
get '/:question_id' do
@question = Question.get params[:question_id]
haml :question
end
# Post a response to a question.
post '/:question_id' do
@question = Question.get params[:question_id]
@question.answers.create :text => params[:answer]
end
get '/stylesheets/application.css' do
content_type 'text/css'
sass :stylesheet
end
__END__
@@ index
%form{ :action => '/', :method => 'post' }
%textarea{ :name => 'question' }
%input{ :type => 'submit', :value => 'Ask this question!' }
@@ question
%h2
Q:
&= @question.text.inspect
- if @question.answers.any?
%ul
- for answer in @question.answers
%li&= answer.text
- else
%p Waiting for answers ...
@@ layout
!!! XML
!!!
%html
%head
%title Not Vark
%link{ :rel => 'stylesheet', :type => 'text/css', :href => '/stylesheets/application.css' }
%body
%h1 Not Vark
= yield
@@ stylesheet
textarea
:width 300px
:height 75px
input
:display block
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment