Permalink
Browse files

Somebody set us up the bomb

  • Loading branch information...
0 parents commit 0495e5795c69e2ef0c362bb3343a587f3d5134c4 @jamesu committed Jan 17, 2011
@@ -0,0 +1,29 @@
+# whatyousay
+
+## What is it?
+
+Simply put, this consolidates chat logs from services such as IRC and talker into a single JSON or HTML document.
+
+Ever wondered what people have been saying about you, but cant be bothered to parse IRC logs? Well now you have no excuse!
+
+## How do i use it?
+
+First make sure you have the required gems, i.e.:
+
+ gem install active_support nokogiri optparse
+
+Then to use, try running:
+
+ ruby whatyousay.rb -t bip -o whattheysaid.json *.log
+
+Which will parse logs as BIP logs and will be dump the results to the whattheysaid.json file.
+
+There are also a few more command-line arguments, i.e.:
+
+ Usage: whatyousay.rb [options] logs
+ -t, --logType TYPE Log Type
+ -c, --channel CHANNEL Set channel
+ -o, --output file Set output
+ -h, --help Display this screen
+
+Have fun!
@@ -0,0 +1,21 @@
+require 'rubygems'
+require 'nokogiri'
+require 'fileutils'
+require 'date'
+require 'time'
+require 'CGI'
+require 'active_support'
+
+require 'log_collection'
+require 'log_entry'
+require 'sender'
+
+# Parsers
+require 'parsers/parser'
+require 'parsers/bip_parser'
+require 'parsers/colloquy_parser'
+require 'parsers/ircii_parser'
+require 'parsers/talker_parser'
+
+require 'html_dumper'
+
@@ -0,0 +1,94 @@
+class HTMLDumper
+
+ def initialize(collection)
+ @collection = collection
+ end
+
+ def write(fs)
+fs.write("<html><head><title>Log</title>
+<style>
+table {
+
+}
+
+tr {
+ font-size: 16px;
+}
+
+tr.event {
+ background: #eee;
+ padding-top: 6px;
+ padding-bottom: 6px;
+}
+
+tr.message {
+ padding-top: 2px;
+ padding-bottom: 2px;
+}
+
+tr.message td {
+ border-bottom: 1px solid #eee;
+}
+
+tr.date {
+ text-align: center;
+ font-weight: bolder;
+ font-size: 20px;
+}
+
+td {
+}
+
+td.date {
+ font-weight: bold;
+ font-size: 12px;
+
+ border-bottom: none;
+ border-left: 1px solid #eee;
+ padding-left: 3px;
+}
+
+td.sender {
+ font-weight: bold;
+ font-size: 14px;
+
+ border-bottom: none;
+ border-right: 1px solid #ccc;
+ text-align: right;
+
+ padding-right: 3px;
+}
+
+td.content {
+ padding-left: 3px;
+ padding-right: 3px;
+}
+
+
+</style>
+</head><body>\n")
+fs.write("<table>\n")
+last_date = nil
+last_sender = nil
+@collection.entries.each do |entry|
+ dt = entry.occurred
+ dt = Date.civil(dt.year, dt.month, dt.day)
+
+ if dt != last_date
+ fs.write("<tr class=\"date\"><td colspan=\"3\">#{dt.to_s}</tr>")
+ last_date = dt
+ end
+ if entry.sender != last_sender
+ sender = entry.sender.nil? ? "[NIL]" : "#{entry.sender.name}"
+ last_sender = entry.sender
+ else
+ sender = ""
+ end
+ content = CGI::escapeHTML((entry.is_action ? "* #{entry.content}" : entry.content))
+ fs.write("<tr class=\"#{entry.type}\"><td class=\"sender\">#{sender}</td><td class=\"content\">#{content}</td><td class=\"date\">#{entry.occurred.strftime('%H:%M:%S')}</td></tr>\n")
+end
+fs.write("</table>\n")
+fs.write("</body></html>\n")
+end
+
+end
@@ -0,0 +1,72 @@
+class LogCollection
+ attr_accessor :entries
+ attr_accessor :senders
+ attr_accessor :source
+
+ def initialize
+ @entries = []
+ @senders = {}
+ @source = nil
+ end
+
+ def add_sender(sender)
+ idt = sender[:ident]
+
+ if idt
+ if @senders.has_key? idt
+ @senders[idt].merge(sender)
+ else
+ @senders[idt] = Sender.new(idt, sender[:name], sender[:hostmask])
+ end
+ else
+ # Look for sender[:name]/sender[:old_name]
+ name = sender[:old_name]||sender[:name]
+ matched_senders = @senders.select do |k, v|
+ if v == name
+ true
+ else
+ false
+ end
+ end
+ matched_senders.first
+ end
+ end
+
+ def add_event(data)
+ sender = if data[:sender]
+ add_sender(data[:sender])
+ else
+ nil
+ end
+
+ log_entry = LogEntry.new(data, sender)
+ log_entry.source = @source
+
+ @entries << log_entry
+ end
+
+ def clean_entries
+ @entries.sort! { |x,y| x.occurred <=> y.occurred }
+
+ last_entry = nil
+ @entries = @entries.reject do |entry|
+ unless last_entry.nil?
+ rej = if entry.occurred == last_entry.occurred &&
+ entry.sender == last_entry.sender &&
+ entry.content.strip == last_entry.content.strip
+ puts "Rejected duplicate..."
+ puts entry.content
+ puts last_entry.content
+ true
+ else
+ false
+ end
+ end
+
+ last_entry = entry
+ rej
+ end
+ end
+
+
+end
@@ -0,0 +1,36 @@
+class LogEntry
+ attr_accessor :occurred, :content, :sender, :type, :source
+
+ # Types
+ # :event => generic event
+ # :userDisconnected => disconnected
+ # :userAvailable => connected
+ # :userLeft => left channel
+ # :userNewNickname => new nick
+ # :reconnected => you reconnected
+ # :message => message
+ # :action => /msg or notice
+
+ def initialize(entry, sender=nil)
+ @sender = sender
+ @occurred = entry[:occurred]
+ @content = entry[:content] || ''
+ @source = entry[:source]
+ @type = entry[:name]
+ end
+
+ def is_action
+ @type == :action
+ end
+
+ def to_loghash(opts={})
+ {
+ :sender => @sender.to_loghash,
+ :occurred => @occurred,
+ :content => @content,
+ :source => @source,
+ :type => @type
+ }
+ end
+
+end
@@ -0,0 +1,84 @@
+class BipParser < Parser
+ LINE_MATCH = /([0-9][0-9])-([0-9][0-9])-([0-9]{4}) ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) (.*)/
+ USER_MATCH = /([^\!]+)\!([^@]+)@([^: ]+)/
+
+ def initialize(collection)
+ super(collection)
+ end
+
+ def reset
+ end
+
+ def extract_sender(name)
+ # either
+ # woot!~woot@pool-173-62-200-183.phlapa.fios.verizon.net:
+ # OR
+ # mgo2.maxgaming.net
+
+ user_host = USER_MATCH.match(name)
+ if user_host
+ {:ident => user_host[2], :name => user_host[1], :host => user_host[3]}
+ else
+ real_name = (name[-1..-1] == ':') ? name[0...-1] : name
+ {:ident => real_name, :name => real_name, :host => nil}
+ end
+ end
+
+ def parse_line(content)
+ # Bip
+ # e.g. 02-03-2010 19:31:31 -!- Afro!~afro@174-22-28-223.eugn.qwest.net has joined #letstalk
+ match = LINE_MATCH.match(content)
+ if match
+ time = Time.utc(match[3].to_i, match[2].to_i, match[1].to_i,
+ match[4].to_i, match[5].to_i, match[6].to_i)
+ words = match[7].split(' ')
+ type = words.first
+
+ if type == '-!-'
+ # System event
+ content = words[2..-1].join(' ')
+
+ base = {
+ :name => :event,
+ :sender => extract_sender(words[1]),
+ :occurred => time,
+ :content => content}
+
+ if content.match(/has quit/)
+ base[:name] = :userDisconnected
+ elsif content.match(/has joined/)
+ base[:name] = :userAvailable
+ elsif content.match(/is now known as (.*)/)
+ #user = $1.match(USER_MATCH)
+ base[:name] = :userNewNickname
+ elsif content.match(/has left/)
+ base[:name] = :userLeft
+ end
+
+ base
+ elsif type[0...1] == '>' or type[0...1] == '<' # > == send, < == recieve
+ # User chat
+
+ sender = nil
+ cnt = nil
+ is_action = (words[1] == '*')
+ if is_action
+ cnt = words[3..-1].join(' ')
+ sender = extract_sender(words[2])
+ else
+ cnt = words[2..-1].join(' ')
+ sender = extract_sender(words[1])
+ end
+
+ return {
+ :name => is_action ? :action : :message,
+ :sender => sender,
+ :occurred => time,
+ :content => cnt}
+ else
+ puts "ERROR >> #{content}"
+ nil
+ end
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 0495e57

Please sign in to comment.