lib/cachai.rb in cachai-0.0.5 vs lib/cachai.rb in cachai-0.0.7
- old
+ new
@@ -1,9 +1,9 @@
require 'sinatra/base'
+require 'sendgrid-ruby'
require 'redis'
require 'json'
-require 'rake'
require_relative 'models'
require_relative 'akismet'
module Cachai
@@ -17,25 +17,32 @@
# use Rack::CommonLogger, LOGGER
# use Rack::Static, :urls => %w(/css /img /js /favicon.ico), :root => 'public'
use ActiveRecord::ConnectionAdapters::ConnectionManagement
+ CACHE_MINUTES = 10 * 60 # 10 minutes
+
def initialize(app, opts = nil)
opts = opts || {}
- @domain = opts.delete(:domain) or raise 'Domain required.'
+ domain = opts.delete(:domain) or raise 'Domain required.'
+ redis_host = opts.delete(:redis_host) || 'localhost'
+ Cachai.domain = domain
+ Cachai.cache = Redis.new(:host => redis_host)
Cachai.load_db!
- redis_host = opts.delete(:redis_host) || 'localhost'
- @redis = Redis.new(:host => redis_host)
-
if key = opts.delete(:akismet_key)
- @akismet = Akismet.new(:api_key => key, :blog => "http://#{@domain}")
+ @akismet = Akismet.new(:api_key => key, :blog => "http://#{domain}")
else
puts "No Akismet key found! Will not check comments for spam."
end
+ if sendgrid_opts = opts.delete(:sendgrid)
+ @sendgrid = SendGrid::Client.new(sendgrid_opts)
+ @recipient = opts.delete(:recipient) or raise "No recipient set!"
+ end
+
super(app)
end
get '/pingbacks.?:format?' do
# TODO
@@ -46,70 +53,76 @@
end
get '/comments.?:format?' do
check_domain!(params[:domain])
- @redis.del(redis_key(params[:path])) if params[:nocache]
-
# puts "Comments for: #{params[:domain]}#{params[:path]}"
- json_list = get_comments(params[:path])
+ json_list = get_comments(params[:path], params[:nocache])
if params[:callback]
content_type 'application/javascript'
"#{params[:callback]}(#{json_list});"
else
- json(list)
+ json(json_list)
end
end
post '/comments.?:format?' do
begin
data = JSON.parse(request.body.read)
check_domain!(data['domain'])
- headers['Access-Control-Allow-Origin'] = data['protocol'] + '//' + data['domain']
+ halt(400, "Missing params") if data['protocol'].blank? or data['path'].blank?
+ headers['Access-Control-Allow-Origin'] = data['protocol'] + '//' + data['domain']
permalink = 'http://' + data['domain'] + data['path']
halt(400, "No spam allowed") if is_spam?(data, permalink, request)
attrs = {
:content => data['content'],
:author_name => data['author_name'],
:author_email => data['author_email'],
:author_url => data['author_url'],
- :parent_id => data['parent_id'],
+ :parent_id => data['parent_id'].to_i,
:author_ip => request.ip
}
post = Post.find_or_create_by_path(data['path'])
response = Response.create!(attrs.merge(:post_id => post.id))
+ Cachai.clear_cache(data['path'])
+ notify_new_response(response, data['path'])
- @redis.del(redis_key(data['path']))
json({ :status => 'ok', :comment => response })
rescue JSON::ParserError
status 400 and json({ :error => 'Invalid JSON.' })
rescue ActiveRecord::RecordInvalid => e
status 422 and json({ :error => e.message })
+ rescue => e
+ puts e.message
+ puts e.backtrace.join("\n")
+ status 500 and "Something went wrong."
end
end
private
+=begin
def set_cache(timestamp)
return if timestamp.nil?
last_modified timestamp
cache_control :public, :must_revalidate, :max_age => 60
end
def prevent_cache
cache_control :public, :no_cache, :no_store, :must_revalidate, :max_age => 0
# expires 1.year.ago
end
+=end
def check_domain!(domain)
- halt(400, 'Invalid domain.') unless domain == @domain
+ halt(400, 'Invalid domain.') unless domain == Cachai.domain
end
def not_found(message = nil)
halt(404, message || 'Not found.')
end
@@ -117,24 +130,26 @@
def json(obj)
content_type 'application/json'
return obj.is_a?(String) ? obj : obj.to_json
end
- def get_comments(path)
- key = redis_key(path)
- unless json_list = @redis.get(key)
+ def get_comments(path, nocache = false)
+ key = Cachai.key_for(path)
+
+ unless !nocache && json_list = Cachai.cache.get(key)
puts "Not cached. Getting from DB: #{path}"
if post = Post.find_by_path(path)
json_list = get_and_sort_comments_for(post).to_json
else
json_list = '[]'
end
- @redis.set(key, json_list)
- @redis.expire(key, 60 * 60) # one hour
+ Cachai.cache.set(key, json_list)
+ Cachai.cache.expire(key, CACHE_MINUTES)
end
+
json_list
end
def get_and_sort_comments_for(post)
result = []
@@ -151,35 +166,45 @@
end
result
end
- def redis_key(path)
- "comments:#{@domain}:#{path}"
- end
-
def is_spam?(data, link, request)
return false unless @akismet
# return true if blacklisted?(name, email, content)
comment = {
- :user_ip => request.ip,
- :referrer => request.referrer,
- :user_agent => request.user_agent,
- :permalink => link,
- :comment_type => 'comment',
- :comment_content => data['content'],
- :comment_author => data['author_name'],
+ :user_ip => request.ip,
+ :referrer => request.referrer,
+ :user_agent => request.user_agent,
+ :permalink => link,
+ :comment_type => 'comment',
+ :comment_content => data['content'],
+ :comment_author => data['author_name'],
:comment_author_url => data['author_url'],
:comment_author_email => data['author_email']
}
if resp = @akismet.check_comment(comment)
# puts resp.inspect
return resp[:spam]
end
false
+ end
+
+ def notify_new_response(response, path)
+ mail = SendGrid::Mail.new do |m|
+ m.to = @recipient
+ m.from = 'comments@' + Cachai.domain
+ m.reply_to = response.author_email
+ m.subject = "New comment from #{response.author_name} at #{path}"
+ m.text = "#{response.content}\n\n--\nhttp://#{Cachai.domain}/#{path}"
+ end
+
+ puts @sendgrid.send(mail)
+ rescue SendGrid::Exception => e
+ puts e.inspect
end
end
end