post regenerations: replace PostRegeneration model with mod actions.

* Remove the PostRegeneration model. Instead just use a mod action
  to log when a post is regenerated.

* Change it so that IQDB is also updated when the image samples are
  regenerated. This is necessary because when the images samples are
  regenerated, the thumbnail may change, which means IQDB needs to be
  updated too. This can happen when regenerating old images with
  transparent backgrounds where the transparency was flattened to black
  instead of white in the thumbnail.

* Only display one "Regenerate image" option in the post sidebar, to
  regenerate both the images and IQDB. Regenerating IQDB only can be
  done through the API. Having two options in the sidebar is too much
  clutter, and it's too confusing for Mods who don't know the difference
  between an IQDB-only regeneration and a full image regeneration.

* Add a confirm prompt to the "Regenerate image" link.
This commit is contained in:
evazion
2021-01-04 15:59:36 -06:00
parent 913ce88024
commit df44937c57
15 changed files with 34 additions and 189 deletions

View File

@@ -1,18 +1,10 @@
class PostRegenerationsController < ApplicationController
respond_to :html, :xml, :json, :js
respond_to :xml, :json, :js
def create
@post_regeneration = authorize PostRegeneration.new(creator: CurrentUser.user, **permitted_attributes(PostRegeneration))
@post_regeneration.execute_category_action!
@post_regeneration.save
@post = authorize Post.find(params[:post_id]), :regenerate?
@post.regenerate!(params[:category], CurrentUser.user)
respond_with(@post_regeneration, location: @post_regeneration.post)
end
def index
@post_regenerations = authorize PostRegeneration.paginated_search(params)
@post_regenerations = @post_regenerations.includes(:creator, :post) if request.format.html?
respond_with(@post_regenerations)
respond_with(@post)
end
end

View File

@@ -29,6 +29,8 @@ class ModAction < ApplicationRecord
post_unban: 45,
post_permanent_delete: 46,
post_move_favorites: 47,
post_regenerate: 48,
post_regenerate_iqdb: 49,
pool_delete: 62,
pool_undelete: 63,
artist_ban: 184,

View File

@@ -1325,6 +1325,22 @@ class Post < ApplicationRecord
end
end
concerning :RegenerationMethods do
def regenerate!(category, user)
if category == "iqdb"
update_iqdb_async
ModAction.log("<@#{user.name}> regenerated IQDB for post ##{id}", :post_regenerate_iqdb, user)
else
media_file = MediaFile.open(file, frame_data: pixiv_ugoira_frame_data)
UploadService::Utils.process_resizes(self, nil, id, media_file: media_file)
update_iqdb_async
ModAction.log("<@#{user.name}> regenerated image samples for post ##{id}", :post_regenerate, user)
end
end
end
module IqdbMethods
extend ActiveSupport::Concern

View File

@@ -1,31 +0,0 @@
class PostRegeneration < ApplicationRecord
belongs_to :creator, :class_name => "User"
belongs_to :post
validates :category, inclusion: %w[iqdb resizes]
module SearchMethods
def search(params)
q = search_attributes(params, :id, :created_at, :updated_at, :category, :creator, :post)
q.apply_default_order(params)
end
end
extend SearchMethods
def execute_category_action!
if category == "iqdb"
post.update_iqdb_async
elsif category == "resizes"
media_file = MediaFile.open(post.file, frame_data: post.pixiv_ugoira_frame_data)
UploadService::Utils.process_resizes(post, nil, post.id, media_file: media_file)
else
# should never happen
raise Error, "Unknown category: #{category}"
end
end
def self.searchable_includes
[:creator, :post]
end
end

View File

@@ -27,6 +27,10 @@ class PostPolicy < ApplicationPolicy
user.is_approver? && record.fav_count > 0 && record.parent_id.present?
end
def regenerate?
user.is_moderator?
end
def delete?
user.is_approver? && !record.is_deleted?
end

View File

@@ -1,9 +0,0 @@
class PostRegenerationPolicy < ApplicationPolicy
def create?
user.is_moderator?
end
def permitted_attributes_for_create
[:post_id, :category]
end
end

View File

@@ -1,5 +1 @@
<% if @post_regeneration.errors.any? %>
Danbooru.error("<%= j @post_regeneration.errors.full_messages.join(',') %>");
<% else %>
Danbooru.notice("Post regenerated");
<% end %>
Danbooru.notice("Post regenerated");

View File

@@ -1,17 +0,0 @@
<div id="c-post-regenerations">
<div id="a-index">
<h1>Post regenerations</h1>
<%= table_for @post_regenerations, width: "100%" do |t| %>
<% t.column "Post", width: "1%" do |regeneration| %>
<%= PostPresenter.preview(regeneration.post, show_deleted: true) %>
<% end %>
<% t.column :category %>
<% t.column "Creator", width: "10%" do |regeneration| %>
<%= compact_time regeneration.created_at %>
<br> by <%= link_to_user regeneration.creator %>
<% end %>
<% end %>
<%= numbered_paginator(@post_regenerations) %>
</div>
</div>

View File

@@ -87,8 +87,7 @@
<% end %>
<% end %>
<% if policy(PostRegeneration).create? %>
<li id="post-option-regenerate-iqdb"><%= link_to "Regenerate IQDB", post_regenerations_path(post_regeneration: {post_id: post.id, category: "iqdb"}), remote: true, method: :post %></li>
<li id="post-option-regenerate-preview"><%= link_to "Regenerate image sizes", post_regenerations_path(post_regeneration: {post_id: post.id, category: "resizes"}), remote: true, method: :post %></li>
<% if policy(post).regenerate? %>
<li id="post-option-regenerate-preview"><%= link_to "Regenerate image", post_regenerations_path(post_id: post.id, category: "resizes"), remote: true, method: :post, "data-confirm": "This will regenerate the posts's thumbnail images. Are you sure?" %></li>
<% end %>
</ul>

View File

@@ -33,7 +33,6 @@
<li id="post-history-moderation"><%= link_to "Moderation", post_events_path(@post.id) %></li>
<li id="post-history-commentary"><%= link_to "Commentary", artist_commentary_versions_path(search: { post_id: @post.id }) %></li>
<li id="post-history-replacements"><%= link_to "Replacements", post_replacements_path(search: {post_id: @post.id }) %></li>
<li id="post-history-regenerations"><%= link_to "Regenerations", post_regenerations_path(search: {post_id: @post.id }) %></li>
</ul>
</section>
<% end %>

View File

@@ -178,7 +178,7 @@ Rails.application.routes.draw do
get :search
end
end
resources :post_regenerations, :only => [:index, :create]
resources :post_regenerations, :only => [:create]
resources :post_replacements, :only => [:index, :new, :create, :update]
resources :post_votes, only: [:index]

View File

@@ -1,13 +0,0 @@
class CreatePostRegenerations < ActiveRecord::Migration[6.0]
def change
create_table :post_regenerations do |t|
t.timestamps
t.integer :creator_id, null: false
t.integer :post_id, null: false
t.string :category, null: false
t.index :creator_id
t.index :post_id
end
end
end

View File

@@ -2724,39 +2724,6 @@ CREATE SEQUENCE public.post_flags_id_seq
ALTER SEQUENCE public.post_flags_id_seq OWNED BY public.post_flags.id;
--
-- Name: post_regenerations; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.post_regenerations (
id bigint NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
creator_id integer NOT NULL,
post_id integer NOT NULL,
category character varying NOT NULL
);
--
-- Name: post_regenerations_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.post_regenerations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: post_regenerations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.post_regenerations_id_seq OWNED BY public.post_regenerations.id;
--
-- Name: post_replacements; Type: TABLE; Schema: public; Owner: -
--
@@ -4170,13 +4137,6 @@ ALTER TABLE ONLY public.post_disapprovals ALTER COLUMN id SET DEFAULT nextval('p
ALTER TABLE ONLY public.post_flags ALTER COLUMN id SET DEFAULT nextval('public.post_flags_id_seq'::regclass);
--
-- Name: post_regenerations id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.post_regenerations ALTER COLUMN id SET DEFAULT nextval('public.post_regenerations_id_seq'::regclass);
--
-- Name: post_replacements id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -4539,14 +4499,6 @@ ALTER TABLE ONLY public.post_flags
ADD CONSTRAINT post_flags_pkey PRIMARY KEY (id);
--
-- Name: post_regenerations post_regenerations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.post_regenerations
ADD CONSTRAINT post_regenerations_pkey PRIMARY KEY (id);
--
-- Name: post_replacements post_replacements_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -6800,20 +6752,6 @@ CREATE INDEX index_post_flags_on_reason_tsvector ON public.post_flags USING gin
CREATE INDEX index_post_flags_on_status ON public.post_flags USING btree (status);
--
-- Name: index_post_regenerations_on_creator_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_post_regenerations_on_creator_id ON public.post_regenerations USING btree (creator_id);
--
-- Name: index_post_regenerations_on_post_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_post_regenerations_on_post_id ON public.post_regenerations USING btree (post_id);
--
-- Name: index_post_replacements_on_creator_id; Type: INDEX; Schema: public; Owner: -
--
@@ -7582,7 +7520,6 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200520060951'),
('20200803022359'),
('20200816175151'),
('20201121180345'),
('20201201211748'),
('20201213052805'),
('20201219201007'),

View File

@@ -1,5 +0,0 @@
FactoryBot.define do
factory(:post_regeneration) do
post factory: :post, source: FFaker::Internet.http_url
end
end

View File

@@ -6,43 +6,18 @@ class PostRegenerationsControllerTest < ActionDispatch::IntegrationTest
@mod = create(:moderator_user, name: "yukari", created_at: 1.month.ago)
as(@mod) do
@post = create(:post, source: "https://google.com", tag_string: "touhou")
@post_regeneration = create(:post_regeneration, creator: @mod, category: "iqdb")
end
end
context "create action" do
should "render" do
assert_difference("PostRegeneration.count") do
post_auth post_regenerations_path, @mod, params: {format: :json, post_regeneration: {post_id: @post.id, category: "iqdb"}}
assert_response :success
end
end
should "not allow non-mods to regenerate posts" do
assert_difference("PostRegeneration.count", 0) do
post_auth post_regenerations_path, create(:user), params: {format: :json, post_regeneration: {post_id: @post.id, category: "iqdb"}}
assert_response 403
end
end
end
context "index action" do
setup do
@admin = create(:admin_user)
as(@admin) { @admin_regeneration = create(:post_regeneration, post: @post, creator: @admin, category: "resizes") }
end
should "render" do
get post_regenerations_path
post_auth post_regenerations_path, @mod, params: { post_id: @post.id, category: "iqdb" }
assert_response :success
end
should respond_to_search({}).with { [@admin_regeneration, @post_regeneration] }
should respond_to_search(category: "iqdb").with { @post_regeneration }
context "using includes" do
should respond_to_search(post_tags_match: "touhou").with { @admin_regeneration }
should respond_to_search(creator: {level: User::Levels::ADMIN}).with { @admin_regeneration }
should "not allow non-mods to regenerate posts" do
post_auth post_regenerations_path, create(:user), params: { post_id: @post.id, category: "iqdb" }
assert_response 403
end
end
end