journalduhacker/app/controllers/home_controller.rb

276 lines
7.3 KiB
Ruby
Raw Normal View History

class HomeController < ApplicationController
2012-07-07 01:00:00 +02:00
STORIES_PER_PAGE = 25
2012-07-07 00:33:27 +02:00
# how many points a story has to have to probably get on the front page
HOT_STORY_POINTS = 5
# how many days old a story can be to get on the bottom half of /recent
RECENT_DAYS_OLD = 3
# for rss feeds, load the user's tag filters if a token is passed
before_filter :find_user_from_rss_token, :only => [ :index, :newest ]
def hidden
@stories = find_stories({ :hidden => true })
@heading = @title = "Hidden Stories"
@cur_url = "/hidden"
render :action => "index"
end
2012-07-01 00:43:45 +02:00
def index
2014-01-25 17:38:07 +01:00
@stories = find_stories
2012-07-01 01:42:53 +02:00
@rss_link ||= "<link rel=\"alternate\" type=\"application/rss+xml\" " <<
"title=\"RSS 2.0\" href=\"/rss" <<
(@user ? "?token=#{@user.rss_token}" : "") << "\" />"
@heading = @title = ""
2012-07-11 22:34:53 +02:00
@cur_url = "/"
2012-07-01 01:42:53 +02:00
respond_to do |format|
format.html { render :action => "index" }
format.rss {
if @user && params[:token].present?
@title = "Private feed for #{@user.username}"
end
render :action => "rss", :layout => false
}
format.json { render :json => @stories }
end
2012-07-01 01:42:53 +02:00
end
2012-07-01 01:42:53 +02:00
def newest
2014-01-25 17:38:07 +01:00
@stories = find_stories({ :newest => true })
@heading = @title = "Newest Stories"
2012-07-11 22:34:53 +02:00
@cur_url = "/newest"
2012-07-01 01:42:53 +02:00
@rss_link = "<link rel=\"alternate\" type=\"application/rss+xml\" " <<
"title=\"RSS 2.0 - Newest Items\" href=\"/newest.rss" <<
(@user ? "?token=#{@user.rss_token}" : "") << "\" />"
2012-07-01 01:42:53 +02:00
respond_to do |format|
format.html { render :action => "index" }
format.rss {
if @user && params[:token].present?
@title += " - Private feed for #{@user.username}"
end
render :action => "rss", :layout => false
}
format.json { render :json => @stories }
2012-07-01 01:42:53 +02:00
end
2012-06-30 21:14:35 +02:00
end
def newest_by_user
2014-01-25 17:38:07 +01:00
by_user = User.where(:username => params[:user]).first!
2014-01-25 17:38:07 +01:00
@stories = find_stories({ :by_user => by_user })
2013-02-14 01:50:51 +01:00
2014-01-25 17:38:07 +01:00
@heading = @title = "Newest Stories by #{by_user.username}"
@cur_url = "/newest/#{by_user.username}"
@newest = true
2014-01-25 17:38:07 +01:00
@for_user = by_user.username
render :action => "index"
end
def recent
@stories = find_stories({ :recent => true })
@heading = @title = "Recent Stories"
@cur_url = "/recent"
render :action => "index"
end
def tagged
@tag = Tag.where(:tag => params[:tag]).first!
2014-01-25 17:38:07 +01:00
@stories = find_stories({ :tag => @tag })
2012-07-01 01:42:53 +02:00
@heading = @title = @tag.description.blank?? @tag.tag : @tag.description
2012-07-11 22:34:53 +02:00
@cur_url = tag_url(@tag.tag)
2012-07-01 01:42:53 +02:00
@rss_link = "<link rel=\"alternate\" type=\"application/rss+xml\" " <<
"title=\"RSS 2.0 - Tagged #{CGI.escape(@tag.tag)} " <<
"(#{CGI.escape(@tag.description.to_s)})\" href=\"/t/" +
2012-07-01 01:42:53 +02:00
"#{CGI.escape(@tag.tag)}.rss\" />"
respond_to do |format|
format.html { render :action => "index" }
format.rss { render :action => "rss", :layout => false }
end
end
2012-07-07 00:33:27 +02:00
def privacy
begin
render :action => "privacy"
rescue
render :text => "<div class=\"box wide\">" <<
"You apparently have no privacy." <<
"</div>", :layout => "application"
end
end
def about
begin
render :action => "about"
rescue
render :text => "<div class=\"box wide\">" <<
"A mystery." <<
"</div>", :layout => "application"
end
end
2012-07-07 00:33:27 +02:00
private
2014-01-25 17:38:07 +01:00
def find_stories(how = {})
@page = how[:page] = 1
if params[:page].to_i > 0
@page = how[:page] = params[:page].to_i
end
# guest views have caching, but don't bother for logged-in users or dev or
# when the user has tag filters
2014-02-06 04:00:55 +01:00
if Rails.env.development? || @user || tags_filtered_by_cookie.any?
2014-01-25 17:38:07 +01:00
stories, @show_more = _find_stories(how)
else
2014-01-25 17:38:07 +01:00
stories, @show_more = Rails.cache.fetch("stories " <<
how.sort.map{|k,v| "#{k}=#{v.to_param}" }.join(" "),
:expires_in => 45) do
2014-01-25 17:38:07 +01:00
_find_stories(how)
end
end
stories
end
2014-01-25 17:38:07 +01:00
def _find_stories(how)
stories = Story.where(:is_expired => false)
2012-07-07 00:33:27 +02:00
if @user && !how[:by_user] && !how[:hidden]
# exclude downvoted and hidden items
stories = stories.where(
Story.arel_table[:id].not_in(
Vote.arel_table.where(
2014-01-25 17:38:07 +01:00
Vote.arel_table[:user_id].eq(@user.id)
).where(
Vote.arel_table[:vote].lteq(0)
).where(
Vote.arel_table[:comment_id].eq(nil)
).project(
Vote.arel_table[:story_id]
)
)
)
elsif @user && how[:hidden]
stories = stories.where(
Story.arel_table[:id].in(
Vote.arel_table.where(
Vote.arel_table[:user_id].eq(@user.id)
).where(
Vote.arel_table[:vote].eq(0)
).where(
Vote.arel_table[:comment_id].eq(nil)
).project(
Vote.arel_table[:story_id]
)
)
)
2012-07-07 00:33:27 +02:00
end
filtered_tag_ids = []
2014-01-25 17:38:07 +01:00
if @user
filtered_tag_ids = @user.tag_filters.map{|tf| tf.tag_id }
else
2014-01-06 23:30:14 +01:00
filtered_tag_ids = tags_filtered_by_cookie.map{|t| t.id }
end
2014-01-25 17:38:07 +01:00
if how[:tag]
stories = stories.where(
Story.arel_table[:id].in(
Tagging.arel_table.where(
Tagging.arel_table[:tag_id].eq(how[:tag].id)
).project(
Tagging.arel_table[:story_id]
)
)
)
2014-01-25 17:38:07 +01:00
elsif how[:by_user]
stories = stories.where(:user_id => how[:by_user].id)
elsif filtered_tag_ids.any?
stories = stories.where(
Story.arel_table[:id].not_in(
Tagging.arel_table.where(
Tagging.arel_table[:tag_id].in(filtered_tag_ids)
).project(
Tagging.arel_table[:story_id]
)
)
)
2012-07-07 00:33:27 +02:00
end
if how[:recent] && how[:page] == 1
# try to help recently-submitted stories that didn't gain traction
story_ids = []
10.times do |x|
# grab the list of stories from the past n days, shifting out popular
# stories that did gain traction
story_ids = stories.select(:id, :upvotes, :downvotes).
where(Story.arel_table[:created_at].gt((RECENT_DAYS_OLD + x).days.ago)).
order("stories.created_at DESC").
reject{|s| s.score > HOT_STORY_POINTS }
if story_ids.length > STORIES_PER_PAGE + 1
# keep the top half (newest stories)
keep_ids = story_ids[0 .. ((STORIES_PER_PAGE + 1) * 0.5)]
story_ids = story_ids[keep_ids.length - 1 ... story_ids.length]
# make the bottom half a random selection of older stories
while keep_ids.length <= STORIES_PER_PAGE + 1
story_ids.shuffle!
keep_ids.push story_ids.shift
end
stories = Story.where(:id => keep_ids)
break
end
end
end
stories = stories.includes(
:user, :taggings => :tag
).limit(
STORIES_PER_PAGE + 1
).offset(
(how[:page] - 1) * STORIES_PER_PAGE
).order(
(how[:newest] || how[:recent]) ? "stories.created_at DESC" : "hotness"
2013-12-30 23:29:00 +01:00
).to_a
2012-07-07 00:33:27 +02:00
show_more = false
2012-07-07 00:33:27 +02:00
if stories.count > STORIES_PER_PAGE
show_more = true
2012-07-07 00:33:27 +02:00
stories.pop
end
2014-01-25 17:38:07 +01:00
if @user
votes = Vote.votes_by_user_for_stories_hash(@user.id, stories.map(&:id))
2012-07-07 00:33:27 +02:00
stories.each do |s|
if votes[s.id]
s.vote = votes[s.id]
end
end
end
[ stories, show_more ]
2012-07-07 00:33:27 +02:00
end
end