/
mailjunk.rb
99 lines (88 loc) · 2.68 KB
/
mailjunk.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
require 'haml'
require 'json'
require 'redis'
require 'sinatra'
get '/' do
haml :index
end
get '/count' do
content_type :json
{ :query => Mailjunk.parse_opts(params),
:count => Mailjunk.count(params)
}.to_json
end
get '/by_:type' do
content_type :json
type = params.delete('type')
results = Mailjunk.count_by(type, params)
{ :query => ["by_#{type}"] + Mailjunk.parse_opts(params),
:count => results.count,
Mailjunk.plural(type) => results
}.to_json
end
class Mailjunk
PREFIX = 'mailjunk'
AVAILABLE_KEYS = [:result, :day, :month, :status, :domain]
@@redis = Redis.new
class << self
# parse options into keys for redis sets
#
# parse_opts(:result => 'bounced', :status => '4.0.0', :domain => 'gmail.com', :month => '2011.02')
# => ['mailjunk:bounced', 'mailjunk:status:4.0.0', 'mailjunk:domain:gmail.com', 'mailjunk:month:2011.02']
#
# available keys:
# :result => 'delivered' || 'bounced'
# :day => '2011.04.19'
# :month => '2011.04'
# :status => '2.0.0'
# :domain => 'gmail.com'
#
def parse_opts(options)
options.inject([]){|keys, (key, val)|
next(keys) unless AVAILABLE_KEYS.include?(key.to_sym)
keys << (key.to_s == 'result' ? "#{PREFIX}:#{val}" : "#{PREFIX}:#{key}:#{val}")
}
end
# combine options into a unique compound key
#
# compound_key(:result => 'bounced', :status => '4.0.0', :domain => 'gmail.com', :month => '2011.02')
# => "mailjunk:result:bounced&status:4.0.0&domain:gmail.com&month:2011.02"
#
def compound_key(options)
Hash[options.sort].inject("#{PREFIX}:"){|key, (k,v)|
next(key) unless AVAILABLE_KEYS.include?(k.to_sym)
key << "#{k}:#{v}&"
}.chomp('&')
end
# pluralize a key name
def plural(key)
key.to_s == 'status' ? "#{key}es" : "#{key}s"
end
def count(options)
keys = parse_opts(options)
if keys.length == 1
@@redis.scard(*keys)
else
compound_key = compound_key(options)
@@redis.sinterstore(compound_key, *keys)
@@redis.scard(compound_key)
end
end
def count_by(type, options={})
if type.to_s == 'result'
['bounced', 'delivered'].inject({}){|res, key|
res[key] = Mailjunk.count(options.merge(type => key)); res
}
else
Hash[Mailjunk.indexed_keys(type).inject({}){|res, key|
count = Mailjunk.count(options.merge(type => key))
res[key] = count unless count == 0; res
}.sort]
end
end
def indexed_keys(type)
return [] unless AVAILABLE_KEYS.include?(type.to_sym)
@@redis.smembers("#{PREFIX}:#{plural(type)}")
end
end
end