119 lines
3.3 KiB
Ruby
119 lines
3.3 KiB
Ruby
class IncomingLink < ActiveRecord::Base
|
|
belongs_to :topic
|
|
belongs_to :user
|
|
|
|
validates :url, presence: true
|
|
validate :referer_valid
|
|
|
|
before_validation :extract_domain
|
|
before_validation :extract_topic_and_post
|
|
after_create :update_link_counts
|
|
|
|
def self.add(request,current_user=nil)
|
|
user_id, host, referer = nil
|
|
|
|
if request['u']
|
|
u = User.select(:id).where(username_lower: request['u'].downcase).first
|
|
user_id = u.id if u
|
|
end
|
|
|
|
if request.referer.present?
|
|
begin
|
|
host = URI.parse(request.referer).host
|
|
referer = request.referer[0..999]
|
|
rescue URI::InvalidURIError
|
|
# bad uri, skip
|
|
end
|
|
end
|
|
|
|
if host != request.host && (user_id || referer)
|
|
cid = current_user.id if current_user
|
|
unless cid && cid == user_id
|
|
IncomingLink.create(url: request.url,
|
|
referer: referer,
|
|
user_id: user_id,
|
|
current_user_id: cid,
|
|
ip_address: request.remote_ip)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
|
|
# Internal: Extract the domain from link.
|
|
def extract_domain
|
|
if referer.present?
|
|
# We may get a junk URI, just deal with it
|
|
self.domain = URI.parse(self.referer).host rescue nil
|
|
self.referer = nil unless self.domain
|
|
end
|
|
end
|
|
|
|
# Internal: If link is internal and points to topic/post, extract their IDs.
|
|
def extract_topic_and_post
|
|
if url.present?
|
|
parsed = URI.parse(url)
|
|
|
|
begin
|
|
# TODO achieve same thing with no exception
|
|
params = Rails.application.routes.recognize_path(parsed.path)
|
|
if self.topic_id = params[:topic_id]
|
|
self.post_number = params[:post_number] || 1
|
|
end
|
|
rescue ActionController::RoutingError
|
|
# If we can't route to the url, that's OK. Don't save those two fields.
|
|
end
|
|
end
|
|
end
|
|
|
|
# Internal: Update appropriate link counts.
|
|
def update_link_counts
|
|
if topic_id.present?
|
|
exec_sql("UPDATE topics
|
|
SET incoming_link_count = incoming_link_count + 1
|
|
WHERE id = ?", topic_id)
|
|
if post_number.present?
|
|
exec_sql("UPDATE posts
|
|
SET incoming_link_count = incoming_link_count + 1
|
|
WHERE topic_id = ? and post_number = ?", topic_id, post_number)
|
|
end
|
|
end
|
|
end
|
|
|
|
protected
|
|
|
|
def referer_valid
|
|
return true unless referer
|
|
if (referer.length < 3 || referer.length > 100) || (domain.length < 1 || domain.length > 100)
|
|
# internal, no need to localize
|
|
errors.add(:referer, 'referer is invalid')
|
|
false
|
|
else
|
|
true
|
|
end
|
|
end
|
|
end
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: incoming_links
|
|
#
|
|
# id :integer not null, primary key
|
|
# url :string(1000) not null
|
|
# referer :string(1000)
|
|
# domain :string(100)
|
|
# topic_id :integer
|
|
# post_number :integer
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
# user_id :integer
|
|
# ip_address :inet
|
|
# current_user_id :integer
|
|
#
|
|
# Indexes
|
|
#
|
|
# incoming_index (topic_id,post_number)
|
|
# index_incoming_links_on_created_at_and_domain (created_at,domain)
|
|
# index_incoming_links_on_created_at_and_user_id (created_at,user_id)
|
|
#
|