journalduhacker/app/controllers/stories_controller.rb
joshua stein e940601a2f start on automated story title and tagging suggestions
Rather than keep "poorly titled" and "poorly tagged" as reasons for
flagging, make the user do the work of suggesting new ones.

At some point, suggested taggings will flip to real taggings once
they reach a certain count (to be determined later).  This also has
to take into account tagging sets that don't contain current tags,
for when they need to be removed.

For titles, I'm not yet sure how to handle this in an automated
fashion except for the (probably rare) case of multiple users
submitting the same exact thing, but at least collect them for now.

Issue #207
2015-10-14 20:32:24 -05:00

361 lines
8.8 KiB
Ruby

class StoriesController < ApplicationController
before_filter :require_logged_in_user_or_400,
:only => [ :upvote, :downvote, :unvote, :hide, :unhide, :preview ]
before_filter :require_logged_in_user, :only => [ :destroy, :create, :edit,
:fetch_url_title, :new, :suggest ]
before_filter :find_user_story, :only => [ :destroy, :edit, :undelete,
:update ]
before_filter :find_story!, :only => [ :suggest, :submit_suggestions ]
def create
@title = "Submit Story"
@cur_url = "/stories/new"
@story = Story.new(story_params)
@story.user_id = @user.id
if @story.valid? && !(@story.already_posted_story && !@story.seen_previous)
if @story.save
Countinual.count!("#{Rails.application.shortname}.stories.submitted",
"+1")
return redirect_to @story.comments_path
end
end
return render :action => "new"
end
def destroy
if !@story.is_editable_by_user?(@user)
flash[:error] = "You cannot edit that story."
return redirect_to "/"
end
@story.is_expired = true
@story.editor = @user
if params[:reason].present? && @story.user_id != @user.id
@story.moderation_reason = params[:reason]
end
@story.save(:validate => false)
redirect_to @story.comments_path
end
def edit
if !@story.is_editable_by_user?(@user)
flash[:error] = "You cannot edit that story."
return redirect_to "/"
end
@title = "Edit Story"
if @story.merged_into_story
@story.merge_story_short_id = @story.merged_into_story.short_id
end
end
def fetch_url_attributes
s = Story.new
s.fetching_ip = request.remote_ip
s.url = params[:fetch_url]
oattrs = { :url => params[:fetch_url], :title => nil }
if (title = s.fetched_title).present?
oattrs[:title] = title
end
if (cu = s.fetched_canonical_url).present?
oattrs[:url] = cu
end
return render :json => oattrs
end
def new
@title = "Submit Story"
@cur_url = "/stories/new"
@story = Story.new
@story.fetching_ip = request.remote_ip
if params[:url].present?
@story.url = params[:url]
if (cu = @story.fetched_canonical_url).present? && @story.url != cu
flash.now[:notice] = "Note: URL has been changed to fetched " <<
"canonicalized version"
@story.url = cu
end
if s = Story.find_similar_by_url(@story.url)
if s.is_recent?
# user won't be able to submit this story as new, so just redirect
# them to the previous story
flash[:success] = "This URL has already been submitted recently."
return redirect_to s.comments_path
else
# user will see a warning like with preview screen
@story.already_posted_story = s
end
end
# ignore what the user brought unless we need it as a fallback
@story.title = @story.fetched_title
if !@story.title.present? && params[:title].present?
@story.title = params[:title]
end
end
end
def preview
@story = Story.new(story_params)
@story.user_id = @user.id
@story.previewing = true
@story.vote = Vote.new(:vote => 1)
@story.upvotes = 1
@story.valid?
@story.seen_previous = true
return render :action => "new", :layout => false
end
def show
@story = Story.where(:short_id => params[:id]).first!
if @story.merged_into_story
flash[:success] = "\"#{@story.title}\" has been merged into this story."
return redirect_to @story.merged_into_story.comments_path
end
if @story.can_be_seen_by_user?(@user)
@title = @story.title
else
@title = "[Story removed]"
end
@short_url = @story.short_id_url
@comments = @story.merged_comments.includes(:user, :story,
:hat).arrange_for_user(@user)
if params[:comment_short_id]
@comments.each do |c,x|
if c.short_id == params[:comment_short_id]
c.highlighted = true
break
end
end
end
respond_to do |format|
format.html {
@comment = @story.comments.build
load_user_votes
render :action => "show"
}
format.json {
render :json => @story.as_json(:with_comments => @comments)
}
end
end
def suggest
if (st = @story.suggested_taggings.where(:user_id => @user.id)).any?
@story.tags_a = st.map{|st| st.tag.tag }
end
if tt = @story.suggested_titles.where(:user_id => @user.id).first
@story.title = tt.title
end
end
def submit_suggestions
ostory = @story.dup
@story.title = params[:story][:title]
if @story.valid?
if @story.title != ostory.title
@story.save_suggested_title_for_user!(@story.title, @user)
end
if @story.tags_a.sort != params[:story][:tags_a].sort
@story.save_suggested_tags_a_for_user!(params[:story][:tags_a], @user)
end
flash[:success] = "Your suggested changes have been noted."
redirect_to ostory.comments_path
else
render :action => "suggest"
end
end
def undelete
if !(@story.is_editable_by_user?(@user) &&
@story.is_undeletable_by_user?(@user))
flash[:error] = "You cannot edit that story."
return redirect_to "/"
end
@story.is_expired = false
@story.editor = @user
@story.save(:validate => false)
redirect_to @story.comments_path
end
def update
if !@story.is_editable_by_user?(@user)
flash[:error] = "You cannot edit that story."
return redirect_to "/"
end
@story.is_expired = false
@story.editor = @user
if @story.url_is_editable_by_user?(@user)
@story.attributes = story_params
else
@story.attributes = story_params.except(:url)
end
if @story.save
return redirect_to @story.comments_path
else
return render :action => "edit"
end
end
def unvote
if !(story = find_story)
return render :text => "can't find story", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(0, story.id,
nil, @user.id, nil)
render :text => "ok"
end
def upvote
if !(story = find_story)
return render :text => "can't find story", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(1, story.id,
nil, @user.id, nil)
render :text => "ok"
end
def downvote
if !(story = find_story)
return render :text => "can't find story", :status => 400
end
if !Vote::STORY_REASONS[params[:reason]]
return render :text => "invalid reason", :status => 400
end
if !@user.can_downvote?(story)
return render :text => "not permitted to downvote", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(-1, story.id,
nil, @user.id, params[:reason])
render :text => "ok"
end
def hide
if !(story = find_story)
return render :text => "can't find story", :status => 400
end
HiddenStory.hide_story_for_user(story.id, @user.id)
render :text => "ok"
end
def unhide
if !(story = find_story)
return render :text => "can't find story", :status => 400
end
HiddenStory.where(:user_id => @user.id, :story_id => story.id).delete_all
render :text => "ok"
end
private
def story_params
p = params.require(:story).permit(
:title, :url, :description, :moderation_reason, :seen_previous,
:merge_story_short_id, :is_unavailable, :user_is_author, :tags_a => [],
)
if @user.is_moderator?
p
else
p.except(:moderation_reason, :merge_story_short_id, :is_unavailable)
end
end
def find_story
story = Story.where(:short_id => params[:story_id]).first
if @user && story
story.vote = Vote.where(:user_id => @user.id,
:story_id => story.id, :comment_id => nil).first.try(:vote)
end
story
end
def find_story!
@story = find_story
if !@story
raise ActiveRecord::RecordNotFound
end
end
def find_user_story
if @user.is_moderator?
@story = Story.where(:short_id => params[:story_id] || params[:id]).first
else
@story = Story.where(:user_id => @user.id, :short_id =>
(params[:story_id] || params[:id])).first
end
if !@story
flash[:error] = "Could not find story or you are not authorized " <<
"to manage it."
redirect_to "/"
return false
end
end
def load_user_votes
if @user
if v = Vote.where(:user_id => @user.id, :story_id => @story.id,
:comment_id => nil).first
@story.vote = { :vote => v.vote, :reason => v.reason }
end
@story.is_hidden_by_cur_user = @story.is_hidden_by_user?(@user)
@votes = Vote.comment_votes_by_user_for_story_hash(@user.id, @story.id)
@comments.each do |c|
if @votes[c.id]
c.current_vote = @votes[c.id]
end
end
end
end
end