Skip to content

Commit

Permalink
Major refactoring and API redesign
Browse files Browse the repository at this point in the history
  • Loading branch information
ezkl committed Mar 3, 2012
1 parent c64016f commit 28f05b1
Show file tree
Hide file tree
Showing 29 changed files with 2,851 additions and 1,193 deletions.
2 changes: 1 addition & 1 deletion .rspec
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
--color
--format progress
--format documentation
2 changes: 1 addition & 1 deletion Guardfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
guard 'rspec', :version => 2 do
guard 'rspec', :cli => '--color --format=documentation', :version => 2 do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
Expand Down
48 changes: 27 additions & 21 deletions lib/sniffles.rb
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
require 'nokogiri'

require "sniffles/version"
require 'sniffles/version'
require 'sniffles/sniffers'
require 'sniffles/utils'
require 'sniffles/html'
require 'sniffles/text'

module Sniffles
def self.sniff(html)
doc = Nokogiri::HTML::parse(html)

module Sniffles
def self.sniff(response_body, *sniffers_or_groups)
output = {}
output[:wordpress] = true if wordpress?(doc)
output[:jquery] = true if jquery?(html)
output[:quantcast] = true if quantcast?(html)
output[:mixpanel] = true if mixpanel?(html)

sniffers_or_groups.each do |sniffer_or_group|
if list_all.include?(sniffer_or_group)
output[sniffer_or_group] = Sniffers.use(response_body, sniffer_or_group)
elsif list_groups.include?(sniffer_or_group)
list_all_by_group[sniffer_or_group].each do |sniffer|
output[sniffer] = Sniffers.use(response_body, sniffer)
end
else
raise UnknownSniffer, "#{sniffer} not found!"
end
end
output
end

def self.wordpress?(doc)
!doc.xpath('.//link[contains(@href,"wp-content")]').empty?
def self.list_all
Sniffers.list_all
end
def self.jquery?(html)
!!(html =~ /jQuery/)

def self.list_groups
Sniffers.list_groups
end

def self.quantcast?(html)
!!(html =~ /\.quantserve\.com\/quant\.js/)
end

def self.mixpanel?(html)
!!(html =~ /api.mixpanel.com\S+mixpanel.js/)
def self.list_all_by_group
Sniffers.list_all_by_group
end

class UnknownSniffer < Exception;end
end
19 changes: 19 additions & 0 deletions lib/sniffles/html.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Sniffles
module HTML
def parse(html)
@doc = Nokogiri::HTML(html)
end

def text_at(pattern)
if (nodes = @doc.search(pattern)).any?
nodes.text
else
false
end
end

def text_match?(pattern, text)
(@doc.search(pattern).text == text)
end
end
end
30 changes: 30 additions & 0 deletions lib/sniffles/sniffers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Sniffles
module Sniffers
def self.use(response_body, name)
file = Dir.glob("lib/sniffles/sniffers/**/#{name.to_s}.rb").first
class_name = get_sniffer_class(name.to_s)
require File.expand_path(File.dirname(__FILE__) + "/../../#{file}")
eval("Sniffers::#{class_name}.new(response_body).output")
end

def self.list_all(group = "**")
Dir.glob("lib/sniffles/sniffers/#{group}/*.rb").collect do |sniffer|
sniffer.match(/sniffers\/[a-z]+\/(.*)\.rb$/)[1].to_sym
end
end

def self.list_groups
Dir.glob("lib/sniffles/sniffers/**").collect { |group| group.match(/sniffers\/(.*)$/)[1].to_sym }
end

def self.list_all_by_group
output = {}
list_groups.each { |group| output[group] = list_all(group).to_a }
output
end

def self.get_sniffer_class(name)
name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.gsub(/(?:^|[_-])(.)/) { $1.upcase }
end
end
end
29 changes: 29 additions & 0 deletions lib/sniffles/sniffers/analytics/google_analytics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Sniffles
module Sniffers
class GoogleAnalytics
include Text

attr_accessor :doc
attr_reader :output

def initialize(response_body)
@output = {}
parse(response_body) && process_document
end

def process_document
@output[:found] = google_analytics?
parse_google_analytics_ua
end

private
def google_analytics?
match?(/\.google\-analytics\.com|urchinTracker/i)
end

def parse_google_analytics_ua
@output[:ua] = capture(/[\"|\'](UA\-[\d]+\-[\d])[\"|\']/)
end
end
end
end
24 changes: 24 additions & 0 deletions lib/sniffles/sniffers/analytics/mixpanel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Sniffles
module Sniffers
class Mixpanel
include Text

attr_accessor :doc
attr_reader :output

def initialize(response_body)
@output = {}
parse(response_body) && process_document
end

def process_document
@output[:found] = mixpanel?
end

private
def mixpanel?
match?(/api\.mixpanel\.com\S+mixpanel\.js/)
end
end
end
end
24 changes: 24 additions & 0 deletions lib/sniffles/sniffers/analytics/quantcast.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Sniffles
module Sniffers
class Quantcast
include Text

attr_accessor :doc
attr_reader :output

def initialize(response_body)
@output = {}
parse(response_body) && process_document
end

def process_document
@output[:found] = quantcast?
end

private
def quantcast?
match?(/\.quantserve\.com\/quant\.js/)
end
end
end
end
53 changes: 53 additions & 0 deletions lib/sniffles/sniffers/cms/wordpress.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Sniffles
module Sniffers
class Wordpress
include HTML
attr_accessor :doc
attr_reader :name, :group, :output, :response

def initialize(response_body)
@output = {}
parse(response_body) && process_document
end

def process_document
@output[:found] = wordpress?
parse_version
parse_feed
parse_theme
parse_pingback
end

private
def wordpress?
@doc.xpath('//link[contains(@href,"wp-content")]').any?
end

def parse_feed
@output[:feed] = text_at("//link[@rel='alternate' and @type='application/rss+xml']/@href")
end

def parse_theme
theme_uri = text_at("//link[@rel='stylesheet' and contains(@href,'wp-content/themes/')][1]/@href")
@output[:theme] = (theme_uri ? clean_theme_uri(theme_uri)[1] : false)
end

def parse_version
version_meta_tag = text_at("//meta[@name='generator']/@content")
@output[:version] = (version_meta_tag ? extract_version(version_meta_tag)[1] : version_meta_tag)
end

def parse_pingback
@output[:pingback] = text_at("//link[@rel='pingback']/@href")
end

def clean_theme_uri(uri)
/wp-content\/themes\/([^\/]*)\//i.match uri
end

def extract_version(string)
/([\d]+\.[\d]+[\.]?[\d]?)/.match string
end
end
end
end
24 changes: 24 additions & 0 deletions lib/sniffles/sniffers/javascript/jquery.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Sniffles
module Sniffers
class Jquery
include Text

attr_accessor :doc
attr_reader :output

def initialize(response_body)
@output = {}
parse(response_body) && process_document
end

def process_document
@output[:found] = jquery?
end

private
def jquery?
match?(/jQuery/)
end
end
end
end
15 changes: 15 additions & 0 deletions lib/sniffles/text.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Sniffles
module Text
def parse(text)
@doc = text
end

def match?(pattern)
!!(pattern.match(@doc))
end

def capture(pattern)
(captures = pattern.match(@doc)) ? captures[1] : false
end
end
end
7 changes: 7 additions & 0 deletions lib/sniffles/utils.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Sniffles
module Utils
def self.absolute_uri(host, path)
URI.parse(host).merge(URI.parse(path)).to_s
end
end
end
Loading

0 comments on commit 28f05b1

Please sign in to comment.