forked from e621ng/e621ng
Takedowns
This commit is contained in:
parent
d0deccf402
commit
118459af1b
184
app/controllers/takedowns_controller.rb
Normal file
184
app/controllers/takedowns_controller.rb
Normal file
@ -0,0 +1,184 @@
|
||||
class TakedownsController < ApplicationController
|
||||
respond_to :html, :xml, :json
|
||||
before_action :admin_only, only: [:update, :destroy, :add_by_ids, :add_by_tags, :count_matching_posts, :remove_by_id]
|
||||
|
||||
def index
|
||||
@takedowns = Takedown.search(search_params).paginate(params[:page], limit: params[:limit])
|
||||
respond_with(@takedowns)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@takedown = Takedown.find(params[:id])
|
||||
@takedown.destroy
|
||||
end
|
||||
|
||||
def show
|
||||
@takedown = Takedown.find(params[:id])
|
||||
@show_instructions = (CurrentUser.ip_addr == @takedown.creator_ip_addr) || (@takedown.vericode == params[:code])
|
||||
respond_with(@takedown, @show_instructions)
|
||||
end
|
||||
|
||||
def new
|
||||
@takedown = Takedown.new
|
||||
respond_with(@takedown)
|
||||
end
|
||||
|
||||
def create
|
||||
@takedown = Takedown.create(takedown_params)
|
||||
flash[:notice] = @takedown.valid? ? "Takedown created" : @takedown.errors.full_messages.join(". ")
|
||||
if @takedown.valid?
|
||||
redirect_to(takedown_url(@takedown, code: @takedown.vericode))
|
||||
else
|
||||
respond_with(@takedown)
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
takedown = Takedown.find(params[:id])
|
||||
|
||||
takedown.notes = params[:takedown][:notes]
|
||||
takedown.reason_hidden = params[:takedown][:reason_hidden]
|
||||
takedown.approver = current_user.id
|
||||
|
||||
# If the takedown is pending or inactive, and the new status is pending or inactive
|
||||
if ["pending", "inactive"].include?(takedown.status) && ["pending", "inactive"].include?(params[:takedown][:status])
|
||||
takedown.status = params[:takedown][:status]
|
||||
end
|
||||
|
||||
if params[:process_takedown]
|
||||
# Handle posts, delete ones marked for deletion
|
||||
if params[:takedown_posts]
|
||||
params[:takedown_posts].each do |post_id, value|
|
||||
|
||||
takedown_post = TakedownPost.find_by_takedown_id_and_post_id(takedown.id, post_id)
|
||||
|
||||
takedown_post.status = status = (value == "1" ? "deleted" : "kept")
|
||||
takedown_post.save
|
||||
|
||||
if takedown_post.status == "deleted"
|
||||
takedown_post.post.undelete!(current_user) if takedown_post.post.is_deleted?
|
||||
delete_reason = params[:delete_reason].presence || "Artist requested removal"
|
||||
Resque.enqueue(
|
||||
DeletePost,
|
||||
post_id,
|
||||
"takedown ##{takedown.id}: #{delete_reason}",
|
||||
current_user.id,
|
||||
false) #Do not transfer favorites on takedowns.
|
||||
end
|
||||
if takedown_post.post.status == "deleted" && takedown_post.status == "kept"
|
||||
takedown_post.post.undelete!(current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Calculate and update the status (approved, partial, denied) based on number of kept/deleted posts
|
||||
takedown.status = takedown.calculated_status
|
||||
|
||||
ModAction.create(user_id: current_user.id, action: "completed_takedown", values: {takedown_id: takedown.id})
|
||||
end
|
||||
|
||||
if takedown.save
|
||||
respond_to_success("Request updated, status set to #{takedown.status}", {action: "show", id: takedown.id})
|
||||
|
||||
if params[:takedown][:process_takedown] && takedown.email.include?("@")
|
||||
begin
|
||||
UserMailer::deliver_takedown_updated(takedown, current_user)
|
||||
rescue Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
|
||||
flash[:error] = 'Error emailing: ' + e.message
|
||||
end
|
||||
end
|
||||
else
|
||||
respond_to_error(takedown, action: "show", id: takedown.id)
|
||||
end
|
||||
end
|
||||
|
||||
def add_by_ids
|
||||
begin
|
||||
takedown = Takedown.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound => x
|
||||
respond_to_error("Takedown ##{params[:id]} not found", action: "index")
|
||||
return
|
||||
end
|
||||
|
||||
added_post_ids = takedown.add_post_ids(params[:post_ids])
|
||||
api_return = {added_count: added_post_ids.length, added_post_ids: added_post_ids}
|
||||
|
||||
respond_to do |fmt|
|
||||
fmt.html {respond_to_success("#{added_post_ids.length} posts added to takedown ##{params[:id]}", action: "show", id: params[:id])}
|
||||
fmt.xml {render xml: api_return.to_xml}
|
||||
fmt.json {render json: api_return.to_json, callback: params[:callback]}
|
||||
end
|
||||
end
|
||||
|
||||
def add_by_tags
|
||||
begin
|
||||
takedown = Takedown.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound => x
|
||||
respond_to_error("Takedown ##{params[:id]} not found", action: "index")
|
||||
return
|
||||
end
|
||||
|
||||
posts = Post.find_by_sql(Post.generate_sql(
|
||||
QueryParser.parse(params[:tags].to_s + " status:any order:id_asc").join(" "),
|
||||
user: current_user,
|
||||
select: "posts.id"
|
||||
))
|
||||
|
||||
# Collect all post ids into an array
|
||||
post_ids = posts.map(&:id)
|
||||
|
||||
added_post_ids = takedown.add_post_ids(post_ids)
|
||||
api_return = {added_count: added_post_ids.length, added_post_ids: added_post_ids}
|
||||
|
||||
respond_to do |fmt|
|
||||
fmt.html {respond_to_success("#{added_count} posts with tags '#{}' added to takedown ##{params[:id]}", action: "show", id: params[:id])}
|
||||
fmt.xml {render xml: api_return.to_xml}
|
||||
fmt.json {render json: api_return.to_json, callback: params[:callback]}
|
||||
end
|
||||
end
|
||||
|
||||
def count_matching_posts
|
||||
posts = Post.find_by_sql(Post.generate_sql(
|
||||
QueryParser.parse(params[:tags].to_s + " status:any").join(" "),
|
||||
user: current_user,
|
||||
select: "posts.id"
|
||||
))
|
||||
|
||||
api_return = {matched_post_count: posts.length}
|
||||
|
||||
respond_to do |fmt|
|
||||
fmt.xml {render xml: api_return.to_xml}
|
||||
fmt.json {render json: api_return.to_json, callback: params[:callback]}
|
||||
end
|
||||
end
|
||||
|
||||
def remove_by_id
|
||||
begin
|
||||
takedown_post = TakedownPost.find_by_takedown_id_and_post_id(params[:id], params[:post_id])
|
||||
rescue ActiveRecord::RecordNotFound => x
|
||||
respond_to_error("Post ##{params[:post_id]} not found in takedown ##{params[:id]}", action: "show", id: params[:id])
|
||||
return
|
||||
end
|
||||
|
||||
takedown_post.destroy
|
||||
respond_to_success("Post ##{params[:post_id]} removed from takedown ##{params[:id]}", action: "show", id: params[:id])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def search_params
|
||||
permitted_params = %i[status]
|
||||
if CurrentUser.is_admin?
|
||||
permitted_params << %i[source reason ip_addr creator_id creator_name email vericode status order]
|
||||
end
|
||||
params.fetch(:search, {}).permit(*permitted_params)
|
||||
end
|
||||
|
||||
def takedown_params
|
||||
permitted_params = %i[email source instructions reason post_ids reason_hidden]
|
||||
if CurrentUser.is_admin?
|
||||
permitted_params << %i[notes del_post_ids status]
|
||||
end
|
||||
params.require(:takedown).permit(*permitted_params, post_ids: [])
|
||||
end
|
||||
end
|
10
app/helpers/takedowns_helper.rb
Normal file
10
app/helpers/takedowns_helper.rb
Normal file
@ -0,0 +1,10 @@
|
||||
module TakedownsHelper
|
||||
def pretty_status(takedown)
|
||||
status = takedown.pretty_status
|
||||
classes = {'inactive': 'sect_grey',
|
||||
'denied': 'sect_red',
|
||||
'partial': 'sect_green',
|
||||
'approved': 'sect_green'}
|
||||
tag.td(status, class: classes[takedown.status])
|
||||
end
|
||||
end
|
@ -1377,7 +1377,7 @@ class Post < ApplicationRecord
|
||||
end
|
||||
|
||||
def delete!(reason, options = {})
|
||||
if is_status_locked?
|
||||
if is_status_locked? && !options.fetch(:force, false)
|
||||
self.errors.add(:is_status_locked, "; cannot delete post")
|
||||
return false
|
||||
end
|
||||
|
202
app/models/takedown.rb
Normal file
202
app/models/takedown.rb
Normal file
@ -0,0 +1,202 @@
|
||||
class Takedown < ApplicationRecord
|
||||
belongs_to_creator
|
||||
belongs_to :approver
|
||||
before_validation :initialize_fields, on: :create
|
||||
before_validation :normalize_post_ids
|
||||
validates_presence_of :email
|
||||
validates_presence_of :reason
|
||||
validates_format_of :email, with: /\A([\s*A-Z0-9._%+-]+@[\s*A-Z0-9.-]+\.\s*[A-Z\s*]{2,15}\s*)\z/i, on: :create
|
||||
validate :can_create_takedown
|
||||
validate :valid_posts_or_instructions
|
||||
validate :validate_number_of_posts
|
||||
validate :validate_post_ids
|
||||
after_validation :normalize_deleted_post_ids
|
||||
before_save :update_post_count
|
||||
|
||||
PRETTY_STATUS = {
|
||||
'partial': 'Partially Approved'
|
||||
}
|
||||
|
||||
def pretty_status
|
||||
PRETTY_STATUS.fetch(status, status.capitalize)
|
||||
end
|
||||
|
||||
def initialize_fields
|
||||
self.status = "pending"
|
||||
self.vericode = Takedown.create_vericode
|
||||
self.del_post_ids = ''
|
||||
end
|
||||
|
||||
def self.create_vericode
|
||||
consonants = "bcdfghjklmnpqrstvqxyz"
|
||||
vowels = "aeiou"
|
||||
pass = ""
|
||||
|
||||
4.times do
|
||||
pass << consonants[rand(21), 1]
|
||||
pass << vowels[rand(5), 1]
|
||||
end
|
||||
|
||||
pass << rand(100).to_s
|
||||
pass
|
||||
end
|
||||
|
||||
module ValidationMethods
|
||||
def valid_posts_or_instructions
|
||||
errors[:base] << "You must provide post ids or instructions." if post_array.size <= 0 && instructions.blank?
|
||||
end
|
||||
def can_create_takedown
|
||||
return if creator.is_mod?
|
||||
errors[:base] << "You have created a takedown too recently" if self.where('creator_id = ? AND created_at > ?', creator_id, 5.minutes.ago).count > 0
|
||||
errors[:base] << "You have created a takedown too recently" if self.where('creator_ip_addr = ? AND created_at > ?', creator_ip_addr, 5.minutes.ago).count > 0
|
||||
end
|
||||
def validate_number_of_posts
|
||||
if post_array.size > 5_000
|
||||
self.errors.add(:base, "You can only have 5000 posts in a takedown.")
|
||||
return false
|
||||
end
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
module AddPostMethods
|
||||
def add_posts_by_ids!(ids)
|
||||
with_lock do
|
||||
self.post_ids = (post_array + ids.scan(/\d+/).uniq).join(' ')
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
||||
def add_posts_by_tags!(tag_string)
|
||||
new_ids = Post.tag_match(tag_string).limit(1000).map(&:id)
|
||||
add_posts_by_ids!(new_ids)
|
||||
end
|
||||
end
|
||||
|
||||
module PostMethods
|
||||
def normalize_post_ids
|
||||
self.post_ids = post_ids.scan(/\d+/).uniq.join(' ')
|
||||
end
|
||||
|
||||
def normalize_deleted_post_ids
|
||||
posts = post_ids.scan(/\d+/).uniq
|
||||
del_posts = del_post_ids.scan(/\d+/).uniq
|
||||
del_posts = del_posts & posts # ensure that all deleted posts are also posts
|
||||
self.del_post_ids = del_posts.join(' ')
|
||||
end
|
||||
|
||||
def validate_post_ids
|
||||
temp_post_ids = Post.select(:id).where(id: post_array).map {|x| x.id.to_s}
|
||||
self.post_ids = temp_post_ids.join(' ')
|
||||
end
|
||||
|
||||
def self.validated_posts(ids)
|
||||
Post.select(:id).where(id: ids).map {|x| x.id}.to_set
|
||||
end
|
||||
|
||||
def del_post_array
|
||||
@del_post_array ||= del_post_ids.scan(/\d+/).map(&:to_i).to_set
|
||||
end
|
||||
|
||||
def actual_deleted_posts
|
||||
Post.where(id: del_post_array)
|
||||
end
|
||||
|
||||
def post_array
|
||||
@post_array ||= post_ids.scan(/\d+/).map(&:to_i).to_set
|
||||
end
|
||||
|
||||
def actual_kept_posts
|
||||
Post.where(id: kept_post_array)
|
||||
end
|
||||
|
||||
def kept_post_array
|
||||
@kept_post_array ||= post_array - del_post_array
|
||||
end
|
||||
|
||||
def clear_cached_arrays
|
||||
@post_array = nil
|
||||
@del_post_array = nil
|
||||
@kept_post_array = nil
|
||||
end
|
||||
|
||||
def update_post_count
|
||||
normalize_post_ids
|
||||
normalize_deleted_post_ids
|
||||
clear_cached_arrays
|
||||
self.post_count = del_post_array.size
|
||||
end
|
||||
end
|
||||
|
||||
module ProcessMethods
|
||||
|
||||
end
|
||||
|
||||
module SearchMethods
|
||||
def search(params)
|
||||
q = super
|
||||
|
||||
if params[:source].present?
|
||||
q = q.where('source ILIKE ?', params[:source].to_escaped_for_sql_like)
|
||||
end
|
||||
if params[:reason].present?
|
||||
q = q.where('reason ILIKE ?', params[:reason].to_escaped_for_sql_like)
|
||||
end
|
||||
if params[:ip_addr].present?
|
||||
q = q.where('creator_ip_addr <<= ?', params[:ip_addr])
|
||||
end
|
||||
if params[:creator_id].present?
|
||||
q = q.where('creator_id = ?', params[:creator_id])
|
||||
end
|
||||
if params[:creator_name].present?
|
||||
q = q.where('takedowns.creator_id = (select _.id from users _ WHERE lower(_.name) ? ?)', params[:creator_name].tr(' ', '_').downcase)
|
||||
end
|
||||
if params[:email].present?
|
||||
q = q.where('email ILIKE ?', params[:email].to_escaped_for_sql_like)
|
||||
end
|
||||
if params[:vericode].present?
|
||||
q = q.where('vericode = ?', params[:vericode])
|
||||
end
|
||||
if params[:status].present?
|
||||
q = q.where('status = ?', params[:status])
|
||||
end
|
||||
|
||||
params[:order] ||= params.delete(:sort)
|
||||
case params[:order]
|
||||
when 'status'
|
||||
q = q.order('status ASC')
|
||||
when 'post_count'
|
||||
q = q.order('post_count DESC')
|
||||
else
|
||||
q = q.order('id DESC')
|
||||
end
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
module StatusMethods
|
||||
def completed?
|
||||
["approved", "denied", "partial"].include?(status)
|
||||
end
|
||||
|
||||
def calculated_status
|
||||
kept_count = kept_posts_array.size
|
||||
deleted_count = del_posts_array.size
|
||||
|
||||
if kept_count == 0 # All were deleted, so it was approved
|
||||
"approved"
|
||||
elsif deleted_count == 0 # All were kept, so it was denied
|
||||
"denied"
|
||||
else # Some were kept and some were deleted, so it was partially approved
|
||||
"partial"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include PostMethods
|
||||
include ValidationMethods
|
||||
include StatusMethods
|
||||
include ProcessMethods
|
||||
include SearchMethods
|
||||
end
|
55
app/views/takedowns/_search.html.erb
Normal file
55
app/views/takedowns/_search.html.erb
Normal file
@ -0,0 +1,55 @@
|
||||
<% unless params[:show] %><div id='searchform_hide'><%= link_to_function "Show Search Options", "$j('#searchform').fadeIn('fast'); $('searchform_hide').hide();" %></div><% end %>
|
||||
<div class='section' style='width:400px;<% unless params[:show] %>display:none;<% end %>' id='searchform'>
|
||||
<% unless params[:show] %><%= link_to_function "Hide Search Options", "$j('#searchform').fadeOut('fast'); $('searchform_hide').show();" %><% end %>
|
||||
<% form_tag({action: "index"}, method: :get) do %>
|
||||
<table class='nomargin'>
|
||||
<tr><td><label for="source">Source</label></td><td><%= text_field_tag "source", params[:source], style: "width:195px"%></td></tr>
|
||||
<tr><td><label for="reason">Reason</label></td><td><%= text_field_tag "reason", params[:reason], style: "width:195px"%></td></tr>
|
||||
<tr><td><label for="notes">Admin Response</label></td><td><%= text_field_tag "notes", params[:notes], style: "width:195px"%></td></tr>
|
||||
|
||||
<% if current_user.is_admin? %>
|
||||
<tr><td><label for="reason_hidden">Reason hidden?</label></td><td>
|
||||
<%= select_tag "reason_hidden", options_for_select([
|
||||
["Any", "any"],
|
||||
["Yes", "true"],
|
||||
["No", "false"],
|
||||
], params[:reason_hidden]), style: "width:200px;" %>
|
||||
</td></tr>
|
||||
|
||||
<tr><td><label for="instructions">Instructions</label></td><td><%= text_field_tag "instructions", params[:instructions], style: "width:195px"%></td></tr>
|
||||
<tr><td><label for="post_id">Post ID</label></td><td><%= text_field_tag "post_id", params[:post_id], style: "width:195px"%></td></tr>
|
||||
<tr><td><label for="email">Email</label></td><td><%= text_field_tag "email", params[:email], style: "width:195px"%></td></tr>
|
||||
<tr><td><label for="ip_addr">IP Address</label></td><td><%= text_field_tag "ip_addr", params[:ip_addr], style: "width:195px"%></td></tr>
|
||||
<tr><td><label for="vericode">Vericode</label></td><td><%= text_field_tag "vericode", params[:vericode], style: "width:195px"%></td></tr>
|
||||
<% end %>
|
||||
|
||||
<tr><td><label for="status">Status</label></td><td>
|
||||
<%= select_tag "status", options_for_select([
|
||||
["Any", "any"],
|
||||
["Pending", "pending"],
|
||||
["Inactive", "inactive"],
|
||||
["Denied", "denied"],
|
||||
["Partially Approved", "partial"],
|
||||
["Approved", "approved"]
|
||||
], params[:status]), style: "width:200px;" %>
|
||||
</td></tr>
|
||||
<tr><td><label for="order">Order</label></td><td>
|
||||
<%= select_tag "order", options_for_select([
|
||||
["Date", "date"],
|
||||
["Source", "source"],
|
||||
["Email", "email"],
|
||||
["IP Address", "ip_addr"],
|
||||
["Status", "status"],
|
||||
["Post count", "post_count"]
|
||||
], params[:order]), style: "width:200px;" %>
|
||||
</td></tr>
|
||||
<tr><td colspan="2"><%= submit_tag "Search", name: nil %></td></tr>
|
||||
</table>
|
||||
<% if params[:show] %>
|
||||
<input type='hidden' name='show' value='1'/>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if params[:source] || params[:reason] || params[:notes] || params[:reason_hidden] || params[:instructions] || params[:post_id] || params[:email] || params[:ip_addr] || params[:vericode] || params[:status] || params[:order] %>
|
||||
<script type='text/javascript'>$('searchform_hide').hide(); $('searchform').show();</script>
|
||||
<% end %>
|
9
app/views/takedowns/_secondary_links.html.erb
Normal file
9
app/views/takedowns/_secondary_links.html.erb
Normal file
@ -0,0 +1,9 @@
|
||||
<% content_for(:secondary_links) do %>
|
||||
<menu>
|
||||
<%= subnav_link_to "Listing", takedowns_path %>
|
||||
<%= subnav_link_to "New", new_takedown_path %>
|
||||
<% if CurrentUser.is_admin? && params[:action] == 'show' %>
|
||||
<%= subnav_link_to 'Delete', {action: 'destroy', id: @takedown.id}, confirm: 'Are you sure you want to dele this takedown?' %>
|
||||
<% end %>
|
||||
</menu>
|
||||
<% end %>
|
372
app/views/takedowns/edit.html.erb
Normal file
372
app/views/takedowns/edit.html.erb
Normal file
@ -0,0 +1,372 @@
|
||||
<div id="c-takedowns">
|
||||
<div id="c-edit">
|
||||
<h2>Takedown #<%= @takedown.id %></h2>
|
||||
<div class='section'>
|
||||
<table style="margin-bottom:0px;">
|
||||
<tr>
|
||||
<td><span class='title'>Source</span></td>
|
||||
<td>
|
||||
<% if !@takedown.reason_hidden || current_user.is_admin? || @show_instructions %>
|
||||
<% if @takedown.source.match(/^https?:\/\//i) %>
|
||||
<a href='<%= h @takedown.source %>'><%= h @takedown.source %></a>
|
||||
<% else %>
|
||||
<a href='<%= h "http://" + @takedown.source %>'><%= h @takedown.source %></a>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span class="redtext">[Source hidden by submitter]</span>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Reason</span></td>
|
||||
<% if !@takedown.reason_hidden || current_user.is_admin? || @show_instructions %>
|
||||
<td><%= h @takedown.reason %>
|
||||
<% if @takedown.reason_hidden %><span class="redtext">(HIDDEN)</span>
|
||||
<% end %></td>
|
||||
<% else %>
|
||||
<td><span class="redtext">[Reason hidden by submitter]</span></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
|
||||
<% if current_user.is_admin? %>
|
||||
<tr>
|
||||
<td><span class='title'>Vericode</span></td>
|
||||
<td><%= @takedown.vericode %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Email</span></td>
|
||||
<td><a href="mailto:<%= h @takedown.email %>"><%= h @takedown.email %></a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>IP Addr</span></td>
|
||||
<td><%= ip_to_link(@takedown.ip_addr) %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>User</span></td>
|
||||
<td><%= link_to_if(@takedown.user, @takedown.user_name, controller: :user, action: :show, id: @takedown.user ? @takedown.user.id : 0) %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Created</span></td>
|
||||
<td style="cursor:help;" title="<%= @takedown.created_at.strftime("%b %d, %Y %I:%M %p") %>"><%= time_ago_in_words(@takedown.created_at) %>
|
||||
ago
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<% if @takedown.created_at != @takedown.updated_at %>
|
||||
<tr>
|
||||
<td><span class='title'>Handled</span></td>
|
||||
<td style="cursor:help;" title="<%= @takedown.updated_at.strftime("%b %d, %Y %I:%M %p") %>"><%= time_ago_in_words(@takedown.updated_at) %>
|
||||
ago
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Status</span></td>
|
||||
<td>
|
||||
<% if @takedown.status == "pending" %>
|
||||
Pending
|
||||
<% elsif @takedown.status == "inactive" %>
|
||||
Inactive
|
||||
<% elsif @takedown.status == "partial" %>
|
||||
<span class='yellowtext'>Partially Approved</span>
|
||||
<% elsif @takedown.status == "denied" %>
|
||||
<span class='redtext'>Denied</span>
|
||||
<% elsif @takedown.status == "approved" %>
|
||||
<span class='greentext'>Approved</span>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<% if @takedown.status != "pending" %>
|
||||
<tr>
|
||||
<td><span class='title'>Approver</span></td>
|
||||
|
||||
<td><%= link_to User.find(@takedown.approver).name, {controller: "user", action: "show", id: @takedown.approver} %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<% if !@takedown.notes.blank? && @takedown.notes.downcase != "none" %>
|
||||
<h3>Admin notes</h3>
|
||||
<div class="section">
|
||||
<% if !@takedown.reason_hidden || current_user.is_admin? %>
|
||||
<%= format_text(@takedown.notes) %>
|
||||
<% if @takedown.reason_hidden %><span class="redtext">(HIDDEN)</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span class="redtext">[Admin notes hidden]</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @show_instructions || current_user.is_admin? %>
|
||||
<% if !@takedown.instructions.blank? %>
|
||||
<h3>Special instructions</h3>
|
||||
<div class="section">
|
||||
<%= h @takedown.instructions %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @takedown.status == "pending" && !current_user.is_admin? && !@takedown.takedown_posts.blank? %>
|
||||
<div class='section'>
|
||||
<p>The following posts are up for dispute:</p>
|
||||
<% @takedown.kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "inactive" && !@takedown.takedown_posts.blank? %>
|
||||
<div class='section sect_grey'>
|
||||
<p style="margin-bottom:0px;">This takedown request has been marked as inactive as the submitter has not
|
||||
responded in a reasonable time frame. It will be handled once the submitter responds.</p>
|
||||
<% if !current_user.is_admin? %>
|
||||
<br>
|
||||
<p>The following posts are up for dispute:</p>
|
||||
<% @takedown.kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}) %><br>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "denied" %>
|
||||
<div class='section sect_red'>
|
||||
<p>The request has been denied. The following posts were not removed:</p>
|
||||
<% @takedown.kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "partial" %>
|
||||
<div class='section sect_green'>
|
||||
<p>The request has been partially approved. The following posts were removed:</p>
|
||||
<% @takedown.deleted_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}, class: "takedown_post_deleted") %>
|
||||
<br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class='section sect_red'>
|
||||
<p>The following posts were kept:</p>
|
||||
<% @takedown.kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}, class: "takedown_post_kept") %>
|
||||
<br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "approved" %>
|
||||
<div class='section sect_green'>
|
||||
<p>The request has been approved. The following posts were removed:</p>
|
||||
<% @takedown.deleted_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% elsif !current_user.is_admin? %>
|
||||
<div class="section">
|
||||
Post lists and special instructions are not visible to users.
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.is_admin? %>
|
||||
<% form_tag(controller: "takedown", action: "update") do %>
|
||||
<%= hidden_field_tag "id", @takedown.id %>
|
||||
|
||||
<h2>Post list</h2>
|
||||
<div id="takedown-posts" class="section">
|
||||
<%= check_box_tag "process_takedown", true, true %>
|
||||
<label for="process_takedown">Process takedown and delete posts</label>
|
||||
<br><br>
|
||||
|
||||
<label for="takedown_post_delete_reason">Post deletion reason</label><br>
|
||||
<%= text_field_tag "delete_reason", "Artist requested removal", {size: 80} %>
|
||||
<br><br>
|
||||
|
||||
<div id="takedown-keepall" class="takedown-post-label takedown-postall-label takedown-post-keep">Keep all
|
||||
</div>
|
||||
<div id="takedown-deleteall" class="takedown-post-label takedown-postall-label takedown-post-delete">Delete
|
||||
all
|
||||
</div>
|
||||
<br><br>
|
||||
|
||||
<div id="takedown-post-buttons">
|
||||
<% @takedown.takedown_posts.each do |post| %>
|
||||
<% if post.post %>
|
||||
<div id="takedown-post-<%= post.post_id %>" data-post-id="<%= post.post_id %>" class="takedown-post">
|
||||
<div class="takedown-post-label takedown-post-remove" title="Remove this post from the takedown">X</div>
|
||||
<label for="takedown_posts_<%= post.post_id %>" class="takedown-post-label"><%= check_box "takedown_posts", post.post_id, checked: post.status == "deleted" %>
|
||||
<span>Keep</span></label>
|
||||
|
||||
<span class="<%= post.post.status == 'deleted' ? 'redtext' : 'greentext' %>">
|
||||
<%= link_to("post ##{post.post_id}", {controller: "post", action: "show", id: post.post_id}) %>
|
||||
</span>
|
||||
</div>
|
||||
<% else %>
|
||||
<div id="takedown-post-<%= post.post_id %>" data-post-id="<%= post.post_id %>" class="takedown-post">
|
||||
<div class="takedown-post-label takedown-post-remove" title="Remove this post from the takedown">X</div>
|
||||
Post <%= post.post_id %> was destroyed or not found.
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<label for="takedown-add-posts-tags">Add posts with tags:</label><br>
|
||||
<%= text_field_tag "takedown-add-posts-tags", "", size: 40 %>
|
||||
<%= button_to_function "Add", "Takedown.add_posts_by_tags_preview(#{@takedown.id}, jQuery('#takedown-add-posts-tags').val());", id: "takedown-add-posts-tags-preview", disabled: true %>
|
||||
<%= button_to_function "Confirm", "Takedown.add_posts_by_tags(#{@takedown.id}, jQuery('#takedown-add-posts-tags').val());", id: "takedown-add-posts-tags-confirm" %>
|
||||
<%= button_to_function "Cancel", "Takedown.add_posts_by_tags_cancel();", id: "takedown-add-posts-tags-cancel" %>
|
||||
<div id="takedown-add-posts-tags-warning"></div>
|
||||
<br><br>
|
||||
|
||||
<label for="takedown-add-posts-ids">Add post IDs to takedown (space-separated):</label><br>
|
||||
<%= text_field_tag "takedown-add-posts-ids", "", size: 40 %>
|
||||
<%= button_to_function "Add", "Takedown.add_posts_by_ids(#{@takedown.id}, jQuery('#takedown-add-posts-ids').val())", id: "takedown-add-posts-ids-submit", disabled: true %>
|
||||
</div>
|
||||
|
||||
<h2>Update</h2>
|
||||
<div class='section'>
|
||||
<table style="margin-bottom:0px;">
|
||||
<% if @takedown.status == "pending" || @takedown.status == "inactive" %>
|
||||
<tr>
|
||||
<td><label for="status">Status</label></td>
|
||||
<td><%= select_tag "takedown[status]", options_for_select([["Pending", "pending"], ["Inactive", "inactive"]], @takedown.status) %>
|
||||
<span id="post-status-select"></span></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<tr>
|
||||
<td><label for="takedown_notes">Admin notes</label></td>
|
||||
<td>
|
||||
<textarea id="takedown_notes" rows="6" name="takedown[notes]" cols="62"><%= @takedown.notes %></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan='2'><%= check_box "takedown", "reason_hidden", checked: @takedown.reason_hidden %>
|
||||
<label for="takedown_reason_hidden">Hide Reason?
|
||||
(Currently
|
||||
<% if !@takedown.reason_hidden %><span class='greentext'>not hidden</span>
|
||||
<% else %><span class='redtext'>hidden</span>
|
||||
<% end %>)
|
||||
</label></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<%= submit_tag "Submit", value: "Update" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render partial: "secondary_links" %>
|
||||
|
||||
<script type="text/javascript">
|
||||
jQuery(function () {
|
||||
jQuery("body").on("change", "[id^='takedown_posts_']", function () {
|
||||
// Update labels when checkboxes are changed
|
||||
var label = jQuery("label[for=" + jQuery(this).attr("id") + "]");
|
||||
if (jQuery(this).prop("checked"))
|
||||
label.removeClass("takedown-post-keep").addClass("takedown-post-delete").find("> span").html("Delete");
|
||||
else
|
||||
label.removeClass("takedown-post-delete").addClass("takedown-post-keep").find("> span").html("Keep");
|
||||
|
||||
// Update text next to status dropdown based on kept/deleted post count
|
||||
var kept_count = jQuery("label.takedown-post-keep").length;
|
||||
var deleted_count = jQuery("label.takedown-post-delete").length;
|
||||
|
||||
if (kept_count == 0) { // None are kept, so takedown status will be 'approved'
|
||||
jQuery("#post-status-select").html("Status will be set to Approved");
|
||||
} else if (deleted_count == 0) { // None are deleted, so takedown status will be 'denied'
|
||||
jQuery("#post-status-select").html("Status will be set to Denied");
|
||||
} else { // Some kept, some deleted, so takedown status will be 'partial'
|
||||
jQuery("#post-status-select").html("Status will be set to Partially Approved");
|
||||
}
|
||||
});
|
||||
|
||||
var originalHeight = jQuery("#takedown-posts").height();
|
||||
// Toggle post list div based on 'process takedown' checkbox state
|
||||
jQuery("#process_takedown").change(function () {
|
||||
if (jQuery(this).prop("checked")) {
|
||||
// Animate to the original height since jquery can't animate to 'auto', then set height back to auto after the animation finishes
|
||||
jQuery("#takedown-posts").animate({
|
||||
height: originalHeight,
|
||||
}, 500, function () {
|
||||
jQuery(this).css("height", "auto");
|
||||
});
|
||||
|
||||
jQuery("#takedown_status").attr("disabled", true);
|
||||
jQuery("#post-status-select").fadeIn();
|
||||
} else {
|
||||
originalHeight = jQuery("#takedown-posts").height();
|
||||
jQuery("#takedown-posts").animate({
|
||||
height: 20,
|
||||
}, 500);
|
||||
|
||||
jQuery("#takedown_status").attr("disabled", false);
|
||||
jQuery("#post-status-select").fadeOut();
|
||||
}
|
||||
});
|
||||
|
||||
// Delete all
|
||||
jQuery("#takedown-deleteall").click(function () {
|
||||
jQuery("[id^='takedown_posts_']").each(function () {
|
||||
jQuery(this).prop("checked", true).trigger("change");
|
||||
});
|
||||
});
|
||||
|
||||
// Keep all
|
||||
jQuery("#takedown-keepall").click(function () {
|
||||
jQuery("[id^='takedown_posts_']").each(function () {
|
||||
jQuery(this).prop("checked", false).trigger("change");
|
||||
});
|
||||
});
|
||||
|
||||
// Remove post
|
||||
jQuery("body").on("click", ".takedown-post-remove", function () {
|
||||
Takedown.remove_post(<%= @takedown.id %>, jQuery(this).parent().data("post-id"));
|
||||
});
|
||||
|
||||
// Enable/disable add-post input submit buttons if input is filled/blank
|
||||
jQuery("#takedown-add-posts-tags").keyup(function (e) {
|
||||
jQuery("#takedown-add-posts-tags-preview").prop("disabled", jQuery(this).val().length == 0)
|
||||
});
|
||||
jQuery("#takedown-add-posts-ids").keyup(function (e) {
|
||||
jQuery("#takedown-add-posts-ids-submit").prop("disabled", jQuery(this).val().length == 0)
|
||||
});
|
||||
|
||||
// Handle enter keys in add-post inputs
|
||||
jQuery("#takedown-add-posts-tags").keydown(function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
jQuery("#takedown-add-posts-tags-preview:enabled").click();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
jQuery("#takedown-add-posts-ids").keydown(function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
jQuery("#takedown-add-posts-ids-submit:enabled").click();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Trigger change event for elements to run their update handlers
|
||||
jQuery("#process_takedown").trigger("change");
|
||||
jQuery("[id^='takedown_posts_']").trigger("change");
|
||||
});
|
||||
</script>
|
62
app/views/takedowns/index.html.erb
Normal file
62
app/views/takedowns/index.html.erb
Normal file
@ -0,0 +1,62 @@
|
||||
<div id="c-takedowns">
|
||||
<div id="a-index">
|
||||
<%#= render 'search', path: takedowns_path %>
|
||||
<table class="striped" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Source</th>
|
||||
<% if CurrentUser.is_admin? %>
|
||||
<th>Email</th>
|
||||
<th>IP Address</th>
|
||||
<% end %>
|
||||
<th>Status</th>
|
||||
<th>>Post count</th>
|
||||
<th>Date</th>
|
||||
<th width="5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @takedowns.each do |takedown| %>
|
||||
<%= content_tag(:tr, id: "takedown-#{takedown.id}") do %>
|
||||
<td><%= link_to takedown.id, takedown_path(takedown) %></td>
|
||||
<td>
|
||||
<% if !takedown.reason_hidden || CurrentUser.is_admin? %>
|
||||
<% if takedown.source.match(/\Ahttps?:\/\//i) %>
|
||||
<%= link_to takedown.source, takedown.source %>
|
||||
<% else %>
|
||||
<%= link_to takedown.source, "https://#{takedown.source}" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span class="redtext">(Source hidden)</span>
|
||||
<% end %>
|
||||
</td>
|
||||
|
||||
<% if CurrentUser.is_admin? %>
|
||||
<td><%= takedown.email %></td>
|
||||
<td><%= takedown.ip_addr %></td>
|
||||
<% end %>
|
||||
|
||||
<%= pretty_status(takedown.status) %>
|
||||
|
||||
<td><%= takedown.post_count %></td>
|
||||
|
||||
<td><%= time_ago_in_words_tagged takedown.created_at %></td>
|
||||
<% if Currentuser.is_admin? %>
|
||||
<!-- <td><%#= link_to_function "Delete", "if (confirm('Do you really want to delete this takedown?')) {Takedown.destroy(#{takedown.id})}" %></td>-->
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= numbered_paginator(@takedowns) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render "takedowns/secondary_links" %>
|
||||
|
||||
<% content_for(:page_title) do %>
|
||||
Takedowns - <%= Danbooru.config.app_name %>
|
||||
<% end %>
|
57
app/views/takedowns/new.html.erb
Normal file
57
app/views/takedowns/new.html.erb
Normal file
@ -0,0 +1,57 @@
|
||||
<div id="c-takedowns">
|
||||
<div id="c-new">
|
||||
<h4>You may request a takedown by submitting the following form.</h4>
|
||||
<p>Please read our <%#= link_to "takedown policy page", {controller: "static", action: "takedown"} %> before submitting a takedown request form. This form is for use ONLY by people who have a legitimate copyright/trademark infringement claim.</p>
|
||||
<p>If you feel you need to handle a takedown request with an admin personally, you can email <%= Danbooru.config.takedown_email %></p>
|
||||
<br>
|
||||
|
||||
<%= simple_form_for(@takedown) do |f| %>
|
||||
<div class='section' style='width:600px;'>
|
||||
<label for="takedown_source">Your Gallery URL (FurAffinity, deviantArt, personal site, etc.)</label>
|
||||
|
||||
<p class='nomargin'>Example:</p>
|
||||
<ul>
|
||||
<li>http://www.furaffinity.net/user/your_name</li>
|
||||
<li>http://your_name.deviantart.com</li>
|
||||
<li>http://mywebsite.com</li>
|
||||
</ul>
|
||||
<p class='nomargin'>In the next step, you will send a private message from the gallery account you specify, or an e-mail from your website's address/domain.</p>
|
||||
<%= f.input :source, as: :string, required: true %>
|
||||
</div>
|
||||
|
||||
<div class='section' style='width:600px;'>
|
||||
<label for="takedown_email">Your Email Address</label>
|
||||
<p class='nomargin'>Used to contact you if we need further information, and to inform you when the request is completed. It is only visible to admins and will not be used for any other purpose than to contact you regarding your takedown request.</p>
|
||||
|
||||
<%= f.input :email, as: :string, required: true %>
|
||||
</div>
|
||||
|
||||
<div class='section' style='width:600px;'>
|
||||
<label for="takedown_post_list">IDs or URLs of the offending images</label>
|
||||
<p class='nomargin'>A list of either image IDs (like 75512) or URLs (like http://<%= Danbooru.config.server_host %>/post/show/75512), one per line.</p>
|
||||
<%= f.input :post_ids, as: :text, label: 'Posts' %>
|
||||
|
||||
<div class='takedown-instructions-header'>OR</div>
|
||||
|
||||
<label for="takedown_instructions">Special instructions</label>
|
||||
<p class="nomargin">You can supply instructions instead of a list of posts to delete. Example: "Delete everything with the tag john_doe"</p>
|
||||
<%= f.input :instructions, as: :text, label: 'Special Instructions' %>
|
||||
</div>
|
||||
|
||||
<div class='section' style='width:600px;'>
|
||||
<label for="takedown_reason">Reason for takedown request</label><br>
|
||||
|
||||
<p class='nomargin'>Why do you want the artwork to be removed?</p>
|
||||
<%= f.input :reason, as: :text, required: true %>
|
||||
<br>
|
||||
<%= f.input :reason_hidden, label: 'Hide Reason From Public' %><label for="takedown_reason_hidden">Hide the reason from the public?</label><br>Note: This is only to be used if your takedown request contains sensitive or private information. It is NOT for hiding reasons such as "No one asked me for permission". The site administration may remove this checkmark from your takedown request if it's been added unnecessarily.</label>
|
||||
</div>
|
||||
|
||||
<p style='font-weight:bold;'>For the quickest processing of your takedown request, please follow the additional instructions that are displayed on the next page after your request has been submitted.</p>
|
||||
|
||||
<%= f.button :submit, "Submit" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render partial: 'secondary_links' %>
|
180
app/views/takedowns/show.html.erb
Normal file
180
app/views/takedowns/show.html.erb
Normal file
@ -0,0 +1,180 @@
|
||||
<div id="c-takedowns">
|
||||
<div id="c-show">
|
||||
<% if @show_instructions && (!@takedown.completed?) %>
|
||||
<div class='section sect_red' style='padding-top:15px; padding-bottom:1px;'>
|
||||
<div style="font-size:200%;margin-top:-10px;margin-bottom:10px;">Wait! You're not done yet!</div>
|
||||
<p>Your verification code is <span class='takedown-vericode'><%= @takedown.vericode %></span></p>
|
||||
<p>Your takedown request has been successfully created. Using the gallery account that you specified below as the "source", <span style="font-weight:bold;">please send your verification code via PM/note to</span>:</p>
|
||||
|
||||
<ul>
|
||||
<%# Danbooru.config.takedown_links.each do |link| %>
|
||||
<!-- <li><%#= link %></li>-->
|
||||
<%# end %>
|
||||
<li>Or via email from your personal website (e.g. from me@mywebsite.com to <%= Danbooru.config.takedown_email %>)</li>
|
||||
</ul>
|
||||
|
||||
<p>Once you send the verification code, we can process your takedown. This step is necessary in order to confirm that you are who you claim to be.</p>
|
||||
<p>Bookmark this page to be able to access your verification code later, as it will not appear when viewing the takedown otherwise.</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<h2>Takedown #<%= @takedown.id %></h2>
|
||||
<div class='section'>
|
||||
<table style="margin-bottom:0px;">
|
||||
<tr>
|
||||
<td><span class='title'>Source</span></td>
|
||||
<td>
|
||||
<% if !@takedown.reason_hidden || CurrentUser.is_admin? || @show_instructions %>
|
||||
<% if @takedown.source.match(/^https?:\/\//i) %>
|
||||
<a href='<%= h @takedown.source %>'><%= h @takedown.source %></a>
|
||||
<% else %>
|
||||
<a href='<%= h "http://" + @takedown.source %>'><%= h @takedown.source %></a>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span class="redtext">[Source hidden by submitter]</span>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Reason</span></td>
|
||||
<% if !@takedown.reason_hidden || CurrentUser.is_admin? || @show_instructions %>
|
||||
<td><%= h @takedown.reason %>
|
||||
<% if @takedown.reason_hidden %><span class="redtext">(HIDDEN)</span><% end %></td>
|
||||
<% else %>
|
||||
<td><span class="redtext">[Reason hidden by submitter]</span></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
|
||||
<% if CurrentUser.is_admin? %>
|
||||
<tr>
|
||||
<td><span class='title'>Vericode</span></td>
|
||||
<td><%= @takedown.vericode %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Email</span></td>
|
||||
<td><%= link_to @takedown.email, "mailto:#{@takedown.email}" %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>IP Addr</span></td>
|
||||
<td><%= link_to_ip(@takedown.creator_ip_addr) %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>User</span></td>
|
||||
<td><%= link_to_user @takedown.creator %></td>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Created</span></td>
|
||||
<td style="cursor:help;" title="<%= @takedown.created_at.strftime("%b %d, %Y %I:%M %p") %>"><%= time_ago_in_words(@takedown.created_at) %> ago</td>
|
||||
</tr>
|
||||
|
||||
<% if @takedown.created_at != @takedown.updated_at %>
|
||||
<tr>
|
||||
<td><span class='title'>Handled</span></td>
|
||||
<td style="cursor:help;" title="<%= @takedown.updated_at.strftime("%b %d, %Y %I:%M %p") %>"><%= time_ago_in_words(@takedown.updated_at) %> ago</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<tr>
|
||||
<td><span class='title'>Status</span></td>
|
||||
<%= pretty_status(@takedown) %>
|
||||
</tr>
|
||||
|
||||
<% if @takedown.status != "pending" %>
|
||||
<tr>
|
||||
<td><span class='title'>Approver</span></td>
|
||||
|
||||
<td><%= link_to_user @takedown.approver %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<% if !@takedown.notes.blank? && @takedown.notes.downcase != "none" %>
|
||||
<h3>Admin notes</h3>
|
||||
<div class="section">
|
||||
<% if !@takedown.reason_hidden || CurrentUser.is_admin? %>
|
||||
<%= format_text(@takedown.notes) %>
|
||||
<% if @takedown.reason_hidden %><span class="redtext">(HIDDEN)</span><% end %>
|
||||
<% else %>
|
||||
<span class="redtext">[Admin notes hidden]</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @show_instructions || CurrentUser.is_admin? %>
|
||||
<% if !@takedown.instructions.blank? %>
|
||||
<h3>Special instructions</h3>
|
||||
<div class="section">
|
||||
<%= h @takedown.instructions %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @takedown.status == "pending" && !@takedown.kept_post_array.blank? %>
|
||||
<div class='section'>
|
||||
<p>The following posts are up for dispute:</p>
|
||||
<% @takedown.actual_kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.id}", post_path(post)) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "inactive" && !@takedown.takedown_posts.blank? %>
|
||||
<div class='section sect_grey'>
|
||||
<p style="margin-bottom:0px;">This takedown request has been marked as inactive as the submitter has not responded in a reasonable time frame. It will be handled once the submitter responds.</p>
|
||||
<br>
|
||||
<p>The following posts are up for dispute:</p>
|
||||
<% @takedown.actual_kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.id}", post_path(post)) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "denied" %>
|
||||
<div class='section sect_red'>
|
||||
<p>The request has been denied. The following posts were not removed:</p>
|
||||
<% @takedown.actual_kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.id}", post_path(post)) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "partial" %>
|
||||
<div class='section sect_green'>
|
||||
<p>The request has been partially approved. The following posts were removed:</p>
|
||||
<% @takedown.actual_deleted_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.id}", post_path(post), class: "takedown_post_deleted") %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class='section sect_red'>
|
||||
<p>The following posts were kept:</p>
|
||||
<% @takedown.actual_kept_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.id}", post_path(post), class: "takedown_post_kept") %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% elsif @takedown.status == "approved" %>
|
||||
<div class='section sect_green'>
|
||||
<p>The request has been approved. The following posts were removed:</p>
|
||||
<% @takedown.actual_deleted_posts.each do |post| %>
|
||||
<%= link_to("post ##{post.id}", post_path(post)) %><br>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% elsif !CurrentUser.is_admin? %>
|
||||
<div class="section">
|
||||
Post lists and special instructions are not visible to users.
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<%= render partial: "secondary_links" %>
|
@ -40,6 +40,10 @@ module Danbooru
|
||||
"webmaster@#{server_host}"
|
||||
end
|
||||
|
||||
def takedown_email
|
||||
"management@#{server_host}"
|
||||
end
|
||||
|
||||
# System actions, such as sending automated dmails, will be performed with
|
||||
# this account. This account must have Moderator privileges.
|
||||
#
|
||||
|
@ -74,6 +74,17 @@ Rails.application.routes.draw do
|
||||
end
|
||||
end
|
||||
|
||||
resources :takedowns do
|
||||
collection do
|
||||
post :count_matching_posts
|
||||
end
|
||||
member do
|
||||
post :add_by_ids
|
||||
post :add_by_tags
|
||||
post :remove_by_id
|
||||
end
|
||||
end
|
||||
|
||||
resources :artists do
|
||||
member do
|
||||
put :revert
|
||||
|
21
db/migrate/20190222082952_create_takedowns.rb
Normal file
21
db/migrate/20190222082952_create_takedowns.rb
Normal file
@ -0,0 +1,21 @@
|
||||
class CreateTakedowns < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :takedowns do |t|
|
||||
t.timestamps
|
||||
t.integer :creator_id, null: true
|
||||
t.column :creator_ip_addr, :inet, null: false
|
||||
t.integer :approver_id
|
||||
t.string :status, default: 'pending'
|
||||
t.string :vericode, null: false
|
||||
t.string :source
|
||||
t.string :email
|
||||
t.text :reason
|
||||
t.boolean :reason_hidden, null: false, default: false
|
||||
t.text :notes, default: 'none', null: false
|
||||
t.text :instructions
|
||||
t.text :post_ids, default: ''
|
||||
t.text :del_post_ids, default: ''
|
||||
t.integer :post_count, default: 0, null: false
|
||||
end
|
||||
end
|
||||
end
|
@ -1801,6 +1801,50 @@ CREATE SEQUENCE public.tags_id_seq
|
||||
ALTER SEQUENCE public.tags_id_seq OWNED BY public.tags.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: takedowns; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.takedowns (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
creator_id integer,
|
||||
creator_ip_addr inet NOT NULL,
|
||||
approver_id integer,
|
||||
status character varying DEFAULT 'pending'::character varying,
|
||||
vericode character varying NOT NULL,
|
||||
source character varying,
|
||||
email character varying,
|
||||
reason text,
|
||||
reason_hidden boolean DEFAULT false NOT NULL,
|
||||
notes text DEFAULT 'none'::text NOT NULL,
|
||||
instructions text,
|
||||
post_ids text DEFAULT ''::text,
|
||||
del_post_ids text DEFAULT ''::text,
|
||||
post_count integer DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: takedowns_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.takedowns_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: takedowns_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.takedowns_id_seq OWNED BY public.takedowns.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: token_buckets; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@ -2460,6 +2504,13 @@ ALTER TABLE ONLY public.tag_subscriptions ALTER COLUMN id SET DEFAULT nextval('p
|
||||
ALTER TABLE ONLY public.tags ALTER COLUMN id SET DEFAULT nextval('public.tags_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: takedowns id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.takedowns ALTER COLUMN id SET DEFAULT nextval('public.takedowns_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: upload_whitelists id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@ -2892,6 +2943,14 @@ ALTER TABLE ONLY public.tags
|
||||
ADD CONSTRAINT tags_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: takedowns takedowns_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.takedowns
|
||||
ADD CONSTRAINT takedowns_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: upload_whitelists upload_whitelists_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@ -4242,6 +4301,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20190214040324'),
|
||||
('20190214090126'),
|
||||
('20190220025517'),
|
||||
('20190220041928');
|
||||
('20190220041928'),
|
||||
('20190222082952');
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user