-
-
Save sstarr/341094 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Basic titlebot for JsChat (http://jschat.org) | |
# Run 'gem install eventmachine' (with sudo if required) if your computer doesn't have it | |
# gem might also be gem1.8 if you got it from Debian/ubuntu | |
require 'rubygems' | |
require 'eventmachine' | |
require 'json' | |
require 'open-uri' | |
require 'twitter' | |
require 'hpricot' | |
require 'timeout' | |
ROOM = '#jschat' | |
PORT = 6789 | |
SERVER = 'localhost' | |
NAME = 'titlebot' | |
BOT_MASTER = 'simon' | |
URL_REGEX = /\b(([\w-]+:\/\/?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/)))/ | |
TIMEOUT = 5 | |
TOTAL_BYTES = 1024 * 10 | |
# Twitter login details for twatting URLs | |
TWIT_LOGIN = 'your_login' | |
TWIT_PASS = 'your_password' | |
module JsClient | |
module Trigger | |
# You can change these | |
TRIGGERS = [ | |
# Simple | |
{:match => /^hai$/i, :response => 'Hello' }, | |
# Using the sender's name | |
{:match => /!greet/, :response => Proc.new { |response| ["Hello #{response['user']}", "Hai #{response['user']}, sup"][rand(2)] }}, | |
# Matching and random responses | |
{:match => /y\/n/, :response => Proc.new { |response| ['Yes.', 'No.', 'nah'][rand(3)] }}, | |
{:match => /c\/d/, :response => Proc.new { |response| ['Denied.', 'Confirmed.'][rand(2)] }}, | |
{:match => URL_REGEX, :response => Proc.new { |response| Utility.get_title(response['message'].match(URL_REGEX)[1]) } } | |
] | |
def self.random(response) | |
run_trigger(response, TRIGGERS[rand(TRIGGERS.size)]) | |
end | |
def self.triggered?(response) | |
get_trigger(response) | |
end | |
def self.get_trigger(response) | |
TRIGGERS.find { |trigger| trigger[:match] =~ response['message'] } | |
end | |
def self.run(response) | |
run_trigger(response, get_trigger(response)) | |
end | |
def self.run_trigger(response, trigger) | |
return nil if trigger.nil? | |
return trigger[:response] if trigger[:response].class == String | |
trigger[:response].call(response) | |
end | |
end | |
class Utility | |
def self.get_page_head(url) | |
html = nil | |
status = Timeout::timeout(TIMEOUT) do | |
open(url) do |page| | |
html = page.read(TOTAL_BYTES) | |
end | |
end | |
html | |
end | |
def self.get_title(url) | |
head = get_page_head(url) | |
return unless head | |
doc = Hpricot.parse(head) | |
title = (doc/'title').inner_html.gsub(/\s+/, ' ').strip | |
tweet("#{url} #{title}") | |
return title.empty? ? nil : title | |
rescue | |
nil | |
end | |
def self.tweet(msg) | |
client = Twitter::Client.new(:login => TWIT_LOGIN, :password => TWIT_PASS) | |
client.status(:post, msg) | |
end | |
end | |
class Protocol | |
def initialize(connection) | |
@connection = connection | |
end | |
def legal_commands | |
%w(message joined quit error join names part identified part_notice quit_notice join_notice) | |
end | |
def legal?(command) | |
legal_commands.include? command | |
end | |
def message(json) | |
if json['room'] | |
"#{Time.now.strftime('%H:%M')} [#{json['room']}] <#{json['user']}> #{json['message']}" | |
@connection.handle_privmsg json | |
else | |
"#{Time.now.strftime('%H:%M')} PRIVATE <#{json['user']}> #{json['message']}" | |
end | |
end | |
def join(json) | |
@connection.send_names json['room'] | |
"* User #{json['user']} joined #{json['room']}" | |
end | |
def join_notice(json) | |
@connection.names << json['user'] | |
"* User #{json['user']} joined #{json['room']}" | |
end | |
def part(json) | |
"* You left #{json['room']}" | |
end | |
def part_notice(json) | |
@connection.names.delete json['user'] | |
"* #{json['user']} left #{json['room']}" | |
end | |
def quit(json) | |
@connection.names.delete json['user'] | |
"* User #{json['user']} left #{json['room']}" | |
end | |
def names(json) | |
@connection.names = json | |
"* In this channel: #{json.join(', ')}" | |
end | |
def identified(json) | |
@connection.send_join(ROOM) | |
puts "* You are now known as #{json['name']}" | |
end | |
def error(json) | |
"* [ERROR] #{json['message']}" | |
end | |
alias_method :quit_notice, :quit | |
end | |
def post_init | |
@protocol = Protocol.new self | |
puts 'Connected, identifying...' | |
send_identify NAME | |
send_join ROOM | |
end | |
def names=(names) | |
@nicks = names | |
end | |
include EM::Protocols::LineText2 | |
def receive_line(data) | |
json = JSON.parse(data) | |
# Execute the json | |
if json.has_key?('display') and @protocol.legal? json['display'] | |
@protocol.send(json['display'], json[json['display']]) | |
else | |
puts "* [SERVER] #{data}" | |
end | |
rescue Exception => exception | |
puts "* [CLIENT ERROR] #{exception}" | |
end | |
def send_join(channel) | |
@current_channel = channel | |
send_data({ 'join' => channel }.to_json + "\n") | |
end | |
def send_part(channel = nil) | |
channel = @current_channel if channel.nil? | |
send_data({ 'part' => channel }.to_json + "\n") | |
end | |
def send_names(channel = nil) | |
channel = @current_channel if channel.nil? or channel.strip.empty? | |
send_data({ 'names' => channel }.to_json + "\n") | |
end | |
def send_message(line) | |
send_data({ 'to' => @current_channel, 'send' => line }.to_json + "\n") | |
end | |
def send_private_message(user, message) | |
send_data({ 'to' => user, 'send' => message }.to_json + "\n") | |
end | |
def send_identify(username) | |
send_data({ 'identify' => username }.to_json + "\n") | |
end | |
def handle_privmsg(response) | |
p response | |
return_str = nil | |
if response['user'] == NAME | |
return | |
end | |
if response['message'] =~ /^reload!$/ && response['user'] == BOT_MASTER | |
return_str = "Reloading..." | |
$RELOADING = true | |
load __FILE__ | |
$RELOADING = false | |
elsif Trigger.triggered?(response) | |
return_str = Trigger.run(response) | |
end | |
if return_str | |
send_message return_str | |
end | |
end | |
end | |
unless $RELOADING | |
EM.run do | |
connection = EM.connect SERVER, PORT, JsClient | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment