journalduhacker/app/controllers/comments_controller.rb
2017-05-23 10:30:02 +02:00

342 lines
9.4 KiB
Ruby

class CommentsController < ApplicationController
COMMENTS_PER_PAGE = 20
# for rss feeds, load the user's tag filters if a token is passed
before_filter :find_user_from_rss_token, :only => [ :index ]
before_filter :require_logged_in_user_or_400,
:only => [ :create, :preview, :upvote, :downvote, :unvote ]
# for rss feeds, load the user's tag filters if a token is passed
before_filter :find_user_from_rss_token, :only => [ :index ]
def create
if !(story = Story.where(:short_id => params[:story_id]).first) ||
story.is_gone?
return render :text => "can't find story", :status => 400
end
comment = story.comments.build
comment.comment = params[:comment].to_s
comment.user = @user
if params[:hat_id] && @user.hats.where(:id => params[:hat_id])
comment.hat_id = params[:hat_id]
end
if params[:parent_comment_short_id].present?
if pc = Comment.where(:story_id => story.id, :short_id =>
params[:parent_comment_short_id]).first
comment.parent_comment = pc
else
return render :json => { :error => "invalid parent comment",
:status => 400 }
end
end
# prevent double-clicks of the post button
if params[:preview].blank? &&
(pc = Comment.where(:story_id => story.id, :user_id => @user.id,
:parent_comment_id => comment.parent_comment_id).first)
if (Time.now - pc.created_at) < 5.minutes
comment.errors.add(:comment, "^You have already posted a comment " <<
"here recently.")
return render :partial => "commentbox", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
end
end
if comment.valid? && params[:preview].blank? && comment.save
comment.current_vote = { :vote => 1 }
render :partial => "comments/postedreply", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
else
comment.upvotes = 1
comment.current_vote = { :vote => 1 }
preview comment
end
end
def show
if !((comment = find_comment) && comment.is_editable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
render :partial => "comment", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
end
def show_short_id
if !(comment = find_comment)
return render :text => "can't find comment", :status => 400
end
render :json => comment.as_json
end
def redirect_from_short_id
if comment = find_comment
return redirect_to comment.url
else
return render :text => "can't find comment", :status => 400
end
end
def edit
if !((comment = find_comment) && comment.is_editable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
render :partial => "commentbox", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
end
def reply
if !(parent_comment = find_comment)
return render :text => "can't find comment", :status => 400
end
comment = Comment.new
comment.story = parent_comment.story
comment.parent_comment = parent_comment
render :partial => "commentbox", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
end
def delete
if !((comment = find_comment) && comment.is_deletable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
comment.delete_for_user(@user, params[:reason])
render :partial => "comment", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
end
def undelete
if !((comment = find_comment) && comment.is_undeletable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
comment.undelete_for_user(@user)
render :partial => "comment", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
end
def dragon
if !((comment = find_comment) && @user.is_moderator?)
return render :text => "can't find comment", :status => 400
end
comment.become_dragon_for_user(@user)
render :text => "ok"
end
def undragon
if !((comment = find_comment) && @user.is_moderator?)
return render :text => "can't find comment", :status => 400
end
comment.remove_dragon_for_user(@user)
render :text => "ok"
end
def update
if !((comment = find_comment) && comment.is_editable_by_user?(@user))
return render :text => "can't find comment", :status => 400
end
comment.comment = params[:comment]
comment.hat_id = nil
if params[:hat_id] && @user.hats.where(:id => params[:hat_id])
comment.hat_id = params[:hat_id]
end
if params[:preview].blank? && comment.save
votes = Vote.comment_votes_by_user_for_comment_ids_hash(@user.id,
[comment.id])
comment.current_vote = votes[comment.id]
render :partial => "comments/comment", :layout => false,
:content_type => "text/html", :locals => { :comment => comment }
else
comment.current_vote = { :vote => 1 }
preview comment
end
end
def unvote
if !(comment = find_comment)
return render :text => "can't find comment", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(0, comment.story_id,
comment.id, @user.id, nil)
render :text => "ok"
end
def upvote
if !(comment = find_comment)
return render :text => "can't find comment", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(1, comment.story_id,
comment.id, @user.id, params[:reason])
render :text => "ok"
end
def downvote
if !(comment = find_comment)
return render :text => "can't find comment", :status => 400
end
if !Vote::COMMENT_REASONS[params[:reason]]
return render :text => "invalid reason", :status => 400
end
if !@user.can_downvote?(comment)
return render :text => "not permitted to downvote", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(-1, comment.story_id,
comment.id, @user.id, params[:reason])
render :text => "ok"
end
def index
@rss_link ||= { :title => "RSS 2.0 - Newest Comments",
:href => "/comments.rss#{@user ? "?token=#{@user.rss_token}" : ""}" }
@heading = @title = I18n.t 'controllers.comments_controller.commentstitle'
@cur_url = "/comments"
@page = params[:page].to_i
if @page == 0
@page = 1
elsif @page < 0 || @page > (2 ** 32)
raise ActionController::RoutingError.new("page out of bounds")
end
@comments = Comment.where(
:is_deleted => false, :is_moderated => false
).order(
"id DESC"
).offset(
(@page - 1) * COMMENTS_PER_PAGE
).limit(
COMMENTS_PER_PAGE
).includes(
:user, :story
)
if @user
@comments = @comments.where("story_id NOT IN (SELECT story_id FROM " <<
"hidden_stories WHERE user_id = ?)", @user.id)
@votes = Vote.comment_votes_by_user_for_comment_ids_hash(@user.id,
@comments.map{|c| c.id })
@comments.each do |c|
if @votes[c.id]
c.current_vote = @votes[c.id]
end
end
end
respond_to do |format|
format.html { render :action => "index" }
format.rss {
if @user && params[:token].present?
@title = "Private comments feed for #{@user.username}"
end
render :action => "index.rss", :layout => false
}
end
end
def threads
if params[:user]
@showing_user = User.where(:username => params[:user]).first!
@heading = @title = "Threads for #{@showing_user.username}"
@cur_url = "/threads/#{@showing_user.username}"
elsif !@user
# TODO: show all recent threads
return redirect_to "/login"
else
@showing_user = @user
@heading = @title = I18n.t 'controllers.comments_controller.threadstitle'
@cur_url = "/threads"
end
thread_ids = @showing_user.recent_threads(20,
include_submitted_stories = !!(@user && @user.id == @showing_user.id))
comments = Comment.where(
:thread_id => thread_ids
).includes(
:user, :story, :hat, :votes => :user
).arrange_for_user(
@showing_user
)
comments_by_thread_id = comments.group_by(&:thread_id)
@threads = comments_by_thread_id.values_at(*thread_ids).compact
if @user
@votes = Vote.comment_votes_by_user_for_story_hash(@user.id,
comments.map(&:story_id).uniq)
comments.each do |c|
if @votes[c.id]
c.current_vote = @votes[c.id]
end
end
end
# trim each thread to this user's first response
# XXX: busted
#@threads.each do |th|
# th.each do |c|
# if c.user_id == @user.id
# break
# else
# th.shift
# end
# end
#end
end
private
def preview(comment)
comment.previewing = true
comment.is_deleted = false # show normal preview for deleted comments
render :partial => "comments/commentbox", :layout => false,
:content_type => "text/html", :locals => {
:comment => comment, :show_comment => comment }
end
def find_comment
comment = Comment.where(:short_id => params[:id]).first
if @user && comment
comment.current_vote = Vote.where(:user_id => @user.id,
:story_id => comment.story_id, :comment_id => comment.id).first
end
comment
end
end