2012-06-17 03:15:46 +02:00
|
|
|
class HomeController < ApplicationController
|
2012-07-07 01:00:00 +02:00
|
|
|
STORIES_PER_PAGE = 25
|
2012-07-07 00:33:27 +02:00
|
|
|
|
2014-01-25 18:13:14 +01:00
|
|
|
# how many points a story has to have to probably get on the front page
|
2014-01-24 20:55:21 +01:00
|
|
|
HOT_STORY_POINTS = 5
|
|
|
|
|
2014-01-25 18:13:14 +01:00
|
|
|
# how many days old a story can be to get on the bottom half of /recent
|
|
|
|
RECENT_DAYS_OLD = 3
|
2014-01-24 20:55:21 +01:00
|
|
|
|
2012-09-18 17:38:03 +02:00
|
|
|
# for rss feeds, load the user's tag filters if a token is passed
|
|
|
|
before_filter :find_user_from_rss_token, :only => [ :index, :newest ]
|
|
|
|
|
2014-04-03 17:26:10 +02:00
|
|
|
def about
|
|
|
|
begin
|
|
|
|
render :action => "about"
|
|
|
|
rescue
|
|
|
|
render :text => "<div class=\"box wide\">" <<
|
|
|
|
"A mystery." <<
|
|
|
|
"</div>", :layout => "application"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-03-04 00:14:33 +01:00
|
|
|
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-04-07 03:43:16 +02:00
|
|
|
@stories = find_stories({ :hottest => true })
|
2012-06-17 03:15:46 +02:00
|
|
|
|
2014-03-12 23:50:51 +01:00
|
|
|
@rss_link ||= { :title => "RSS 2.0",
|
|
|
|
:href => "/rss#{@user ? "?token=#{@user.rss_token}" : ""}" }
|
2012-06-17 03:15:46 +02:00
|
|
|
|
2012-09-07 16:18:15 +02:00
|
|
|
@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" }
|
2012-09-18 17:38:03 +02:00
|
|
|
format.rss {
|
|
|
|
if @user && params[:token].present?
|
|
|
|
@title = "Private feed for #{@user.username}"
|
|
|
|
end
|
|
|
|
|
|
|
|
render :action => "rss", :layout => false
|
|
|
|
}
|
2012-12-17 03:05:27 +01:00
|
|
|
format.json { render :json => @stories }
|
2012-06-17 03:15:46 +02:00
|
|
|
end
|
2012-07-01 01:42:53 +02:00
|
|
|
end
|
2012-06-17 03:15:46 +02:00
|
|
|
|
2012-07-01 01:42:53 +02:00
|
|
|
def newest
|
2014-01-25 17:38:07 +01:00
|
|
|
@stories = find_stories({ :newest => true })
|
2012-06-17 03:15:46 +02:00
|
|
|
|
2012-09-07 16:18:15 +02:00
|
|
|
@heading = @title = "Newest Stories"
|
2012-07-11 22:34:53 +02:00
|
|
|
@cur_url = "/newest"
|
2012-06-17 03:15:46 +02:00
|
|
|
|
2014-03-12 23:50:51 +01:00
|
|
|
@rss_link = { :title => "RSS 2.0 - Newest Items",
|
|
|
|
:href => "/newest.rss#{@user ? "?token=#{@user.rss_token}" : ""}" }
|
2012-06-17 03:15:46 +02:00
|
|
|
|
2012-07-01 01:42:53 +02:00
|
|
|
respond_to do |format|
|
|
|
|
format.html { render :action => "index" }
|
2012-09-18 17:38:03 +02:00
|
|
|
format.rss {
|
|
|
|
if @user && params[:token].present?
|
|
|
|
@title += " - Private feed for #{@user.username}"
|
|
|
|
end
|
|
|
|
|
|
|
|
render :action => "rss", :layout => false
|
|
|
|
}
|
2012-12-17 03:05:27 +01:00
|
|
|
format.json { render :json => @stories }
|
2012-07-01 01:42:53 +02:00
|
|
|
end
|
2012-06-30 21:14:35 +02:00
|
|
|
end
|
|
|
|
|
2012-09-04 00:21:41 +02:00
|
|
|
def newest_by_user
|
2014-01-25 17:38:07 +01:00
|
|
|
by_user = User.where(:username => params[:user]).first!
|
2012-09-04 00:21:41 +02:00
|
|
|
|
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}"
|
2012-09-04 00:21:41 +02:00
|
|
|
|
|
|
|
@newest = true
|
2014-01-25 17:38:07 +01:00
|
|
|
@for_user = by_user.username
|
2012-09-04 00:21:41 +02:00
|
|
|
|
|
|
|
render :action => "index"
|
|
|
|
end
|
|
|
|
|
2014-04-03 17:26:10 +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
|
|
|
|
|
2014-01-25 18:13:14 +01:00
|
|
|
def recent
|
|
|
|
@stories = find_stories({ :recent => true })
|
|
|
|
|
|
|
|
@heading = @title = "Recent Stories"
|
|
|
|
@cur_url = "/recent"
|
|
|
|
|
2014-03-12 23:50:51 +01:00
|
|
|
# our content changes every page load, so point at /newest.rss to be stable
|
|
|
|
@rss_link = { :title => "RSS 2.0 - Newest Items",
|
|
|
|
:href => "/newest.rss#{@user ? "?token=#{@user.rss_token}" : ""}" }
|
|
|
|
|
2014-01-25 18:13:14 +01:00
|
|
|
render :action => "index"
|
|
|
|
end
|
|
|
|
|
2012-06-17 03:15:46 +02:00
|
|
|
def tagged
|
2013-12-24 04:20:06 +01:00
|
|
|
@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
|
|
|
|
2012-09-07 16:18:15 +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-06-17 03:15:46 +02:00
|
|
|
|
2014-03-12 23:50:51 +01:00
|
|
|
@rss_link = { :title => "RSS 2.0 - Tagged #{@tag.tag} (#{@tag.description})",
|
|
|
|
:href => "/t/#{@tag.tag}.rss" }
|
2012-07-01 01:42:53 +02:00
|
|
|
|
|
|
|
respond_to do |format|
|
|
|
|
format.html { render :action => "index" }
|
|
|
|
format.rss { render :action => "rss", :layout => false }
|
|
|
|
end
|
2012-06-17 03:15:46 +02:00
|
|
|
end
|
2012-07-07 00:33:27 +02:00
|
|
|
|
2014-04-03 20:20:24 +02:00
|
|
|
TOP_INTVS = { "d" => "Day", "w" => "Week", "m" => "Month", "y" => "Year" }
|
|
|
|
def top
|
|
|
|
@cur_url = "/top"
|
|
|
|
length = { :dur => 1, :intv => "Week" }
|
|
|
|
|
|
|
|
if m = params[:length].to_s.match(/\A(\d+)([#{TOP_INTVS.keys.join}])\z/)
|
|
|
|
length[:dur] = m[1].to_i
|
|
|
|
length[:intv] = TOP_INTVS[m[2]]
|
|
|
|
|
|
|
|
@cur_url << "/#{params[:length]}"
|
|
|
|
end
|
|
|
|
|
|
|
|
@stories = find_stories({ :top => true, :length => length })
|
|
|
|
|
|
|
|
if length[:dur] > 1
|
|
|
|
@heading = @title = "Top Stories of the Past #{length[:dur]} " <<
|
|
|
|
length[:intv] << "s"
|
|
|
|
else
|
|
|
|
@heading = @title = "Top Stories of the Past " << length[:intv]
|
|
|
|
end
|
|
|
|
|
|
|
|
render :action => "index"
|
|
|
|
end
|
|
|
|
|
2012-07-07 00:33:27 +02:00
|
|
|
private
|
2014-01-25 17:38:07 +01:00
|
|
|
def find_stories(how = {})
|
2014-02-16 16:55:32 +01:00
|
|
|
@page = how[:page] = 1
|
2012-07-10 21:43:51 +02:00
|
|
|
if params[:page].to_i > 0
|
2014-02-16 16:55:32 +01:00
|
|
|
@page = how[:page] = params[:page].to_i
|
2012-07-10 21:43:51 +02:00
|
|
|
end
|
|
|
|
|
2013-08-05 09:16:33 +02:00
|
|
|
# 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)
|
2012-07-10 21:43:51 +02:00
|
|
|
else
|
2014-01-25 17:38:07 +01:00
|
|
|
stories, @show_more = Rails.cache.fetch("stories " <<
|
2014-01-25 18:13:14 +01:00
|
|
|
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)
|
2012-07-10 21:43:51 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
stories
|
|
|
|
end
|
|
|
|
|
2014-01-25 17:38:07 +01:00
|
|
|
def _find_stories(how)
|
2014-04-09 00:51:12 +02:00
|
|
|
stories = Story.unmerged.where(:is_expired => false)
|
2012-07-07 00:33:27 +02:00
|
|
|
|
2014-04-07 03:43:16 +02:00
|
|
|
if @user
|
|
|
|
hidden_arel = Vote.arel_table.where(
|
|
|
|
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]
|
2013-12-30 19:48:57 +01:00
|
|
|
)
|
2014-04-09 00:51:12 +02:00
|
|
|
|
2014-04-07 03:43:16 +02:00
|
|
|
if how[:hidden]
|
|
|
|
stories = stories.where(Story.arel_table[:id].in(hidden_arel))
|
|
|
|
elsif !how[:by_user]
|
|
|
|
stories = stories.where(Story.arel_table[:id].not_in(hidden_arel))
|
|
|
|
end
|
2012-07-07 00:33:27 +02:00
|
|
|
end
|
|
|
|
|
2014-04-07 03:43:16 +02:00
|
|
|
if how[:tag] || how[:hottest]
|
|
|
|
stories = stories.where("(CAST(upvotes AS integer) - " <<
|
|
|
|
"CAST(downvotes AS integer)) >= -2")
|
2013-02-08 00:35:20 +01:00
|
|
|
end
|
|
|
|
|
2014-01-25 17:38:07 +01:00
|
|
|
if how[:tag]
|
2013-12-30 19:48:57 +01:00
|
|
|
stories = stories.where(
|
|
|
|
Story.arel_table[:id].in(
|
|
|
|
Tagging.arel_table.where(
|
2014-01-25 18:13:14 +01:00
|
|
|
Tagging.arel_table[:tag_id].eq(how[:tag].id)
|
2013-12-30 19:48:57 +01:00
|
|
|
).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)
|
2014-04-07 03:43:16 +02:00
|
|
|
else
|
|
|
|
filtered_tag_ids = []
|
|
|
|
if @user
|
|
|
|
filtered_tag_ids = @user.tag_filters.map{|tf| tf.tag_id }
|
|
|
|
else
|
|
|
|
filtered_tag_ids = tags_filtered_by_cookie.map{|t| t.id }
|
|
|
|
end
|
2014-04-09 00:51:12 +02:00
|
|
|
|
2014-04-07 03:43:16 +02:00
|
|
|
if 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]
|
|
|
|
)
|
2013-12-30 19:48:57 +01:00
|
|
|
)
|
|
|
|
)
|
2014-04-07 03:43:16 +02:00
|
|
|
end
|
2012-07-07 00:33:27 +02:00
|
|
|
end
|
|
|
|
|
2014-02-16 16:55:32 +01:00
|
|
|
if how[:recent] && how[:page] == 1
|
2014-01-24 20:55:21 +01:00
|
|
|
# try to help recently-submitted stories that didn't gain traction
|
|
|
|
|
2014-02-01 10:39:58 +01:00
|
|
|
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
|
2014-01-24 20:55:21 +01:00
|
|
|
end
|
|
|
|
end
|
2014-04-03 20:20:24 +02:00
|
|
|
elsif how[:top] && how[:length]
|
|
|
|
stories = stories.where("created_at >= (NOW() - INTERVAL " <<
|
|
|
|
"#{how[:length][:dur]} #{how[:length][:intv].upcase})")
|
|
|
|
end
|
|
|
|
|
|
|
|
order = "hotness"
|
2014-06-30 18:56:40 +02:00
|
|
|
if how[:newest] || how[:recent] || how[:tag]
|
2014-04-03 20:20:24 +02:00
|
|
|
order = "stories.created_at DESC"
|
|
|
|
elsif how[:top]
|
|
|
|
order = "(CAST(upvotes AS integer) - CAST(downvotes AS integer)) DESC"
|
2014-01-24 20:55:21 +01:00
|
|
|
end
|
|
|
|
|
2013-12-30 19:48:57 +01:00
|
|
|
stories = stories.includes(
|
2013-12-24 04:20:06 +01:00
|
|
|
:user, :taggings => :tag
|
|
|
|
).limit(
|
|
|
|
STORIES_PER_PAGE + 1
|
|
|
|
).offset(
|
2014-02-16 16:55:32 +01:00
|
|
|
(how[:page] - 1) * STORIES_PER_PAGE
|
2013-12-24 04:20:06 +01:00
|
|
|
).order(
|
2014-04-03 20:20:24 +02:00
|
|
|
order
|
2013-12-30 23:29:00 +01:00
|
|
|
).to_a
|
2012-07-07 00:33:27 +02:00
|
|
|
|
2012-07-10 21:43:51 +02:00
|
|
|
show_more = false
|
2012-07-07 00:33:27 +02:00
|
|
|
if stories.count > STORIES_PER_PAGE
|
2012-07-10 21:43:51 +02:00
|
|
|
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
|
|
|
|
|
2012-07-10 21:43:51 +02:00
|
|
|
[ stories, show_more ]
|
2012-07-07 00:33:27 +02:00
|
|
|
end
|
2012-06-17 03:15:46 +02:00
|
|
|
end
|