app/controllers/alerts_controller.rb
class AlertsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :get_alert, only: :create
before_action :authenticate_caller, only: :create
before_action :is_admin?, only: :index
GA_VISITORS_ALERT_INTERVAL = 30.minutes
TRACTION_ALERT_INTERVAL = 30.minutes
# GET /alerts(.:format)
def create
case @alert[:type].to_sym
when :traction
process_traction_alert(@alert[:data])
when :google_analytics
process_google_analytics(@alert[:data])
end
update_stats
head(:ok)
end
#GET /alerts(.:format)
def index
@alerts = []
[:traction, :google_analytics].each do |type|
count = Redis.current.get(count_key(type))
next if count.nil?
@alerts << { type: type, count: count, data: Redis.current.zrangebyscore(history_key(type), 0, Time.now.to_i, withscores: true) }
end
end
private
def authenticate_caller
valid = true
case @alert[:type].to_sym
when :traction, :google_analytics
valid = (@alert[:key] == "3fEtu89_W13k1")
else
valid = false
end
return head(:forbidden) unless valid
end
def get_alert
@alert = JSON.parse(request.body.read).with_indifferent_access
end
def process_traction_alert(data)
if can_report_traction?(data[:url])
update_history
Redis.current.set(last_sent_key(:traction, data[:url]), Time.now.to_i)
NotifierMailer.alert_admin(:traction, data[:url], data[:message]).deliver
end
end
def process_google_analytics(data)
message = "#{data[:viewers]} viewers on site"
message += "\ntop referrers:#{data[:top_referrers].join("\n")}"
if can_report_visitors?
if data[:viewers] > ENV['SITE_VISITORS_MAX_ALERT_LIMIT']
update_history
Redis.current.set(last_sent_key(:google_analytics), Time.now.to_i)
NotifierMailer.alert_admin(:a_lot_of_visitors, data[:url], message).deliver!
elsif data[:viewers] < ENV['SITE_VISITORS_MIN_ALERT_LIMIT']
update_history
Redis.current.set(last_sent_key(:google_analytics), Time.now.to_i)
NotifierMailer.alert_admin(:too_few_visitors, data[:url], message).deliver!
end
end
end
def can_report_visitors?
Time.at(Redis.current.get(last_sent_key(:google_analytics)).to_i) < GA_VISITORS_ALERT_INTERVAL.ago
end
def can_report_traction?(url)
Time.at(Redis.current.get(last_sent_key(:traction, url)).to_i) < TRACTION_ALERT_INTERVAL.ago
end
def last_sent_key(type, subkey=nil)
key = "alert:#{type}:last_sent"
key += ":#{subkey}" unless subkey.nil?
key
end
def count_key(type)
"alert:#{type}:count"
end
def history_key(type)
"alert:#{type}:history"
end
def update_stats
Redis.current.incr(count_key(@alert[:type]))
end
def update_history
Redis.current.zadd(history_key(@alert[:type]), Time.now.to_i, @alert[:data])
end
end