rubocop: fix various style issues.
This commit is contained in:
2
Rakefile
2
Rakefile
@@ -1,7 +1,7 @@
|
|||||||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||||
|
|
||||||
require File.expand_path('../config/application', __FILE__)
|
require File.expand_path('config/application', __dir__)
|
||||||
require 'rake'
|
require 'rake'
|
||||||
|
|
||||||
Rails.application.load_tasks
|
Rails.application.load_tasks
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
rescue_from Exception, :with => :rescue_exception
|
rescue_from Exception, :with => :rescue_exception
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def self.rescue_with(*klasses, status: 500)
|
def self.rescue_with(*klasses, status: 500)
|
||||||
rescue_from *klasses do |exception|
|
rescue_from(*klasses) do |exception|
|
||||||
render_error_page(status, exception)
|
render_error_page(status, exception)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
def enable_cors
|
def enable_cors
|
||||||
response.headers["Access-Control-Allow-Origin"] = "*"
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
||||||
end
|
end
|
||||||
@@ -61,7 +61,7 @@ class ApplicationController < ActionController::Base
|
|||||||
when ActionController::RoutingError
|
when ActionController::RoutingError
|
||||||
render_error_page(405, exception)
|
render_error_page(405, exception)
|
||||||
when ActionController::UnknownFormat, ActionView::MissingTemplate
|
when ActionController::UnknownFormat, ActionView::MissingTemplate
|
||||||
render_error_page(406, exception, message: "#{request.format.to_s} is not a supported format for this page")
|
render_error_page(406, exception, message: "#{request.format} is not a supported format for this page")
|
||||||
when PaginationExtension::PaginationError
|
when PaginationExtension::PaginationError
|
||||||
render_error_page(410, exception, template: "static/pagination_error", message: "You cannot go beyond page #{Danbooru.config.max_numbered_pages}.")
|
render_error_page(410, exception, template: "static/pagination_error", message: "You cannot go beyond page #{Danbooru.config.max_numbered_pages}.")
|
||||||
when Post::SearchError
|
when Post::SearchError
|
||||||
@@ -80,7 +80,7 @@ class ApplicationController < ActionController::Base
|
|||||||
def render_error_page(status, exception, message: exception.message, template: "static/error", format: request.format.symbol)
|
def render_error_page(status, exception, message: exception.message, template: "static/error", format: request.format.symbol)
|
||||||
@exception = exception
|
@exception = exception
|
||||||
@expected = status < 500
|
@expected = status < 500
|
||||||
@message = message.encode("utf-8", { invalid: :replace, undef: :replace })
|
@message = message.encode("utf-8", invalid: :replace, undef: :replace)
|
||||||
@backtrace = Rails.backtrace_cleaner.clean(@exception.backtrace)
|
@backtrace = Rails.backtrace_cleaner.clean(@exception.backtrace)
|
||||||
format = :html unless format.in?(%i[html json xml js atom])
|
format = :html unless format.in?(%i[html json xml js atom])
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class ArtistUrlsController < ApplicationController
|
|||||||
def index
|
def index
|
||||||
@artist_urls = ArtistUrl.includes(:artist).paginated_search(params)
|
@artist_urls = ArtistUrl.includes(:artist).paginated_search(params)
|
||||||
respond_with(@artist_urls) do |format|
|
respond_with(@artist_urls) do |format|
|
||||||
format.json { render json: @artist_urls.to_json(include: "artist",) }
|
format.json { render json: @artist_urls.to_json(include: "artist") }
|
||||||
format.xml { render xml: @artist_urls.to_xml(include: "artist", root: "artist-urls") }
|
format.xml { render xml: @artist_urls.to_xml(include: "artist", root: "artist-urls") }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class CommentsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def index_for_post
|
def index_for_post
|
||||||
@post = Post.find(params[:post_id])
|
@post = Post.find(params[:post_id])
|
||||||
@comments = @post.comments
|
@comments = @post.comments
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ module Explore
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_date
|
def set_date
|
||||||
@date = params[:date] ? Date.parse(params[:date]) : Date.today
|
@date = params[:date] ? Date.parse(params[:date]) : Date.today
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class ForumPostsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_post
|
def load_post
|
||||||
@forum_post = ForumPost.find(params[:id])
|
@forum_post = ForumPost.find(params[:id])
|
||||||
@forum_topic = @forum_post.topic
|
@forum_topic = @forum_post.topic
|
||||||
|
|||||||
@@ -93,13 +93,12 @@ class ForumTopicsController < ApplicationController
|
|||||||
|
|
||||||
def unsubscribe
|
def unsubscribe
|
||||||
subscription = ForumSubscription.where(:forum_topic_id => @forum_topic.id, :user_id => CurrentUser.user.id).first
|
subscription = ForumSubscription.where(:forum_topic_id => @forum_topic.id, :user_id => CurrentUser.user.id).first
|
||||||
if subscription
|
subscription&.destroy
|
||||||
subscription.destroy
|
|
||||||
end
|
|
||||||
respond_with(@forum_topic)
|
respond_with(@forum_topic)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def normalize_search
|
def normalize_search
|
||||||
if params[:title_matches]
|
if params[:title_matches]
|
||||||
params[:search] ||= {}
|
params[:search] ||= {}
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ class IpAddressesController < ApplicationController
|
|||||||
def index
|
def index
|
||||||
if search_params[:group_by] == "ip_addr"
|
if search_params[:group_by] == "ip_addr"
|
||||||
@ip_addresses = IpAddress.search(search_params).group_by_ip_addr(search_params[:ipv4_masklen], search_params[:ipv6_masklen]).paginate(params[:page], limit: params[:limit] || 1000)
|
@ip_addresses = IpAddress.search(search_params).group_by_ip_addr(search_params[:ipv4_masklen], search_params[:ipv6_masklen]).paginate(params[:page], limit: params[:limit] || 1000)
|
||||||
respond_with(@ip_addresses)
|
|
||||||
elsif search_params[:group_by] == "user"
|
elsif search_params[:group_by] == "user"
|
||||||
@ip_addresses = IpAddress.includes(:user).search(search_params).group_by_user.paginate(params[:page], limit: params[:limit] || 1000)
|
@ip_addresses = IpAddress.includes(:user).search(search_params).group_by_user.paginate(params[:page], limit: params[:limit] || 1000)
|
||||||
respond_with(@ip_addresses)
|
|
||||||
else
|
else
|
||||||
@ip_addresses = IpAddress.includes(:user, :model).paginated_search(params)
|
@ip_addresses = IpAddress.includes(:user, :model).paginated_search(params)
|
||||||
|
end
|
||||||
|
|
||||||
respond_with(@ip_addresses)
|
respond_with(@ip_addresses)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class LegacyController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def tag_query
|
def tag_query
|
||||||
params[:tags] || (params[:post] && params[:post][:tags])
|
params[:tags] || (params[:post] && params[:post][:tags])
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class PoolElementsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def append_pool_to_session(pool)
|
def append_pool_to_session(pool)
|
||||||
recent_pool_ids = session[:recent_pool_ids].to_s.scan(/\d+/)
|
recent_pool_ids = session[:recent_pool_ids].to_s.scan(/\d+/)
|
||||||
recent_pool_ids << pool.id.to_s
|
recent_pool_ids << pool.id.to_s
|
||||||
|
|||||||
@@ -23,13 +23,14 @@ class PostReplacementsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
params[:search][:post_id] = params.delete(:post_id) if params.has_key?(:post_id)
|
params[:search][:post_id] = params.delete(:post_id) if params.key?(:post_id)
|
||||||
@post_replacements = PostReplacement.paginated_search(params)
|
@post_replacements = PostReplacement.paginated_search(params)
|
||||||
|
|
||||||
respond_with(@post_replacements)
|
respond_with(@post_replacements)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_params
|
def create_params
|
||||||
params.require(:post_replacement).permit(:replacement_url, :replacement_file, :final_source, :tags)
|
params.require(:post_replacement).permit(:replacement_url, :replacement_file, :final_source, :tags)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ class SessionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def sign_out
|
def sign_out
|
||||||
destroy()
|
destroy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class TagsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_privilege(tag)
|
def check_privilege(tag)
|
||||||
raise User::PrivilegeError unless tag.editable_by?(CurrentUser.user)
|
raise User::PrivilegeError unless tag.editable_by?(CurrentUser.user)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class UsersController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def check_privilege(user)
|
def check_privilege(user)
|
||||||
raise User::PrivilegeError unless (user.id == CurrentUser.id || CurrentUser.is_admin?)
|
raise User::PrivilegeError unless user.id == CurrentUser.id || CurrentUser.is_admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_params(context)
|
def user_params(context)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class WikiPagesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@wiki_page, _ = WikiPage.find_by_id_or_title(params[:id])
|
@wiki_page, _found_by = WikiPage.find_by_id_or_title(params[:id])
|
||||||
respond_with(@wiki_page)
|
respond_with(@wiki_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ class WikiPagesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@wiki_page, _ = WikiPage.find_by_id_or_title(params[:id])
|
@wiki_page, _found_by = WikiPage.find_by_id_or_title(params[:id])
|
||||||
@wiki_page.update(wiki_page_params(:update))
|
@wiki_page.update(wiki_page_params(:update))
|
||||||
flash[:notice] = @wiki_page.warnings.full_messages.join(".\n \n") if @wiki_page.warnings.any?
|
flash[:notice] = @wiki_page.warnings.full_messages.join(".\n \n") if @wiki_page.warnings.any?
|
||||||
|
|
||||||
@@ -57,13 +57,13 @@ class WikiPagesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@wiki_page, _ = WikiPage.find_by_id_or_title(params[:id])
|
@wiki_page, _found_by = WikiPage.find_by_id_or_title(params[:id])
|
||||||
@wiki_page.update(is_deleted: true)
|
@wiki_page.update(is_deleted: true)
|
||||||
respond_with(@wiki_page)
|
respond_with(@wiki_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
def revert
|
def revert
|
||||||
@wiki_page, _ = WikiPage.find_by_id_or_title(params[:id])
|
@wiki_page, _found_by = WikiPage.find_by_id_or_title(params[:id])
|
||||||
@version = @wiki_page.versions.find(params[:version_id])
|
@version = @wiki_page.versions.find(params[:version_id])
|
||||||
@wiki_page.revert_to!(@version)
|
@wiki_page.revert_to!(@version)
|
||||||
flash[:notice] = "Page was reverted"
|
flash[:notice] = "Page was reverted"
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ module ApplicationHelper
|
|||||||
def error_messages_for(instance_name)
|
def error_messages_for(instance_name)
|
||||||
instance = instance_variable_get("@#{instance_name}")
|
instance = instance_variable_get("@#{instance_name}")
|
||||||
|
|
||||||
if instance && instance.errors.any?
|
if instance&.errors&.any?
|
||||||
%{<div class="error-messages ui-state-error ui-corner-all"><strong>Error</strong>: #{instance.__send__(:errors).full_messages.join(", ")}</div>}.html_safe
|
%{<div class="error-messages ui-state-error ui-corner-all"><strong>Error</strong>: #{instance.__send__(:errors).full_messages.join(", ")}</div>}.html_safe
|
||||||
else
|
else
|
||||||
""
|
""
|
||||||
@@ -133,11 +133,11 @@ module ApplicationHelper
|
|||||||
return "anonymous" if user.blank?
|
return "anonymous" if user.blank?
|
||||||
|
|
||||||
user_class = "user-#{user.level_string.downcase}"
|
user_class = "user-#{user.level_string.downcase}"
|
||||||
user_class = user_class + " user-post-approver" if user.can_approve_posts?
|
user_class += " user-post-approver" if user.can_approve_posts?
|
||||||
user_class = user_class + " user-post-uploader" if user.can_upload_free?
|
user_class += " user-post-uploader" if user.can_upload_free?
|
||||||
user_class = user_class + " user-super-voter" if user.is_super_voter?
|
user_class += " user-super-voter" if user.is_super_voter?
|
||||||
user_class = user_class + " user-banned" if user.is_banned?
|
user_class += " user-banned" if user.is_banned?
|
||||||
user_class = user_class + " with-style" if CurrentUser.user.style_usernames?
|
user_class += " with-style" if CurrentUser.user.style_usernames?
|
||||||
if options[:raw_name]
|
if options[:raw_name]
|
||||||
name = user.name
|
name = user.name
|
||||||
else
|
else
|
||||||
@@ -253,14 +253,12 @@ module ApplicationHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def nav_link_match(controller, url)
|
def nav_link_match(controller, url)
|
||||||
url =~ case controller
|
url =~ case controller
|
||||||
when "sessions", "users", "maintenance/user/password_resets", "admin/users"
|
when "sessions", "users", "maintenance/user/password_resets", "admin/users"
|
||||||
/^\/(session|users)/
|
/^\/(session|users)/
|
||||||
|
|
||||||
when "forum_posts"
|
|
||||||
/^\/forum_topics/
|
|
||||||
|
|
||||||
when "comments"
|
when "comments"
|
||||||
/^\/comments/
|
/^\/comments/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module ArtistVersionsHelper
|
module ArtistVersionsHelper
|
||||||
def artist_versions_listing_type
|
def artist_versions_listing_type
|
||||||
params.dig(:search, :artist_id).present? && CurrentUser.is_member? ? :revert : :standard
|
(params.dig(:search, :artist_id).present? && CurrentUser.is_member?) ? :revert : :standard
|
||||||
end
|
end
|
||||||
|
|
||||||
def artist_version_other_names_diff(artist_version)
|
def artist_version_other_names_diff(artist_version)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ module BulkUpdateRequestsHelper
|
|||||||
"#{btag}remove implication " + link_to(arg1, posts_path(:tags => arg1)) + " (#{arg1_count}) -> " + link_to(arg2, posts_path(:tags => arg2)) + " (#{arg2_count})#{etag}"
|
"#{btag}remove implication " + link_to(arg1, posts_path(:tags => arg1)) + " (#{arg1_count}) -> " + link_to(arg2, posts_path(:tags => arg2)) + " (#{arg2_count})#{etag}"
|
||||||
|
|
||||||
when :mass_update
|
when :mass_update
|
||||||
"#{btag}mass update " + link_to(arg1, posts_path(:tags => arg1)) + " -> " + link_to(arg2, posts_path(:tags => arg2)) + "#{etag}"
|
"#{btag}mass update " + link_to(arg1, posts_path(:tags => arg1)) + " -> " + link_to(arg2, posts_path(:tags => arg2)) + etag.to_s
|
||||||
|
|
||||||
when :change_category
|
when :change_category
|
||||||
arg1_count = Tag.find_by_name(arg1).try(:post_count).to_i
|
arg1_count = Tag.find_by_name(arg1).try(:post_count).to_i
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ module PaginationHelper
|
|||||||
else
|
else
|
||||||
html << numbered_paginator_item(1, records.current_page)
|
html << numbered_paginator_item(1, records.current_page)
|
||||||
html << numbered_paginator_item("...", records.current_page)
|
html << numbered_paginator_item("...", records.current_page)
|
||||||
if records.size > 0
|
if records.present?
|
||||||
right_window = records.current_page + window
|
right_window = records.current_page + window
|
||||||
else
|
else
|
||||||
right_window = records.current_page
|
right_window = records.current_page
|
||||||
@@ -62,13 +62,13 @@ module PaginationHelper
|
|||||||
(records.current_page - window).upto(right_window) do |page|
|
(records.current_page - window).upto(right_window) do |page|
|
||||||
html << numbered_paginator_item(page, records.current_page)
|
html << numbered_paginator_item(page, records.current_page)
|
||||||
end
|
end
|
||||||
if records.size > 0
|
if records.present?
|
||||||
html << numbered_paginator_item("...", records.current_page)
|
html << numbered_paginator_item("...", records.current_page)
|
||||||
html << numbered_paginator_final_item(records.total_pages, records.current_page)
|
html << numbered_paginator_final_item(records.total_pages, records.current_page)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if records.current_page < records.total_pages && records.size > 0
|
if records.current_page < records.total_pages && records.present?
|
||||||
html << "<li class='arrow'>" + link_to(content_tag(:i, nil, class: "fas fa-chevron-right"), nav_params_for(records.current_page + 1), rel: "next", id: "paginator-next", "data-shortcut": "d right") + "</li>"
|
html << "<li class='arrow'>" + link_to(content_tag(:i, nil, class: "fas fa-chevron-right"), nav_params_for(records.current_page + 1), rel: "next", id: "paginator-next", "data-shortcut": "d right") + "</li>"
|
||||||
else
|
else
|
||||||
html << "<li class='arrow'><span>" + content_tag(:i, nil, class: "fas fa-chevron-right") + "</span></li>"
|
html << "<li class='arrow'><span>" + content_tag(:i, nil, class: "fas fa-chevron-right") + "</span></li>"
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ module PostsHelper
|
|||||||
sibling_count = parent_post_set.children.count - 1
|
sibling_count = parent_post_set.children.count - 1
|
||||||
if sibling_count > 0
|
if sibling_count > 0
|
||||||
html << " and has "
|
html << " and has "
|
||||||
text = sibling_count == 1 ? "a sibling" : "#{sibling_count} siblings"
|
text = (sibling_count == 1) ? "a sibling" : "#{sibling_count} siblings"
|
||||||
html << link_to(text, posts_path(:tags => "parent:#{post.parent_id}"))
|
html << link_to(text, posts_path(:tags => "parent:#{post.parent_id}"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ module PostsHelper
|
|||||||
html = ""
|
html = ""
|
||||||
|
|
||||||
html << "This post has "
|
html << "This post has "
|
||||||
text = children_post_set.children.count == 1 ? "a child" : "#{children_post_set.children.count} children"
|
text = (children_post_set.children.count == 1) ? "a child" : "#{children_post_set.children.count} children"
|
||||||
html << link_to(text, posts_path(:tags => "parent:#{post.id}"))
|
html << link_to(text, posts_path(:tags => "parent:#{post.id}"))
|
||||||
|
|
||||||
html << " (#{link_to_wiki "learn more", "help:post_relationships"}) "
|
html << " (#{link_to_wiki "learn more", "help:post_relationships"}) "
|
||||||
@@ -111,9 +111,9 @@ module PostsHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def is_pool_selected?(pool)
|
def is_pool_selected?(pool)
|
||||||
return false if params.has_key?(:q)
|
return false if params.key?(:q)
|
||||||
return false if params.has_key?(:favgroup_id)
|
return false if params.key?(:favgroup_id)
|
||||||
return false if !params.has_key?(:pool_id)
|
return false if !params.key?(:pool_id)
|
||||||
return params[:pool_id].to_i == pool.id
|
return params[:pool_id].to_i == pool.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ module UploadsHelper
|
|||||||
|
|
||||||
when /\Aerror: /
|
when /\Aerror: /
|
||||||
search_params = params[:search].permit!
|
search_params = params[:search].permit!
|
||||||
link_to(upload.sanitized_status, uploads_path(search: search_params.merge({ status: upload.sanitized_status })))
|
link_to(upload.sanitized_status, uploads_path(search: search_params.merge(status: upload.sanitized_status)))
|
||||||
|
|
||||||
else
|
else
|
||||||
search_params = params[:search].permit!
|
search_params = params[:search].permit!
|
||||||
link_to(upload.status, uploads_path(search: search_params.merge({ status: upload.status })))
|
link_to(upload.status, uploads_path(search: search_params.merge(status: upload.status)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module UsersHelper
|
module UsersHelper
|
||||||
def email_sig(user)
|
def email_sig(user)
|
||||||
verifier = ActiveSupport::MessageVerifier.new(Danbooru.config.email_key, serializer: JSON, digest: "SHA256")
|
verifier = ActiveSupport::MessageVerifier.new(Danbooru.config.email_key, serializer: JSON, digest: "SHA256")
|
||||||
verifier.generate("#{user.id}")
|
verifier.generate(user.id.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ module WikiPageVersionsHelper
|
|||||||
if chg.new_element.match(/^\r?\n$/)
|
if chg.new_element.match(/^\r?\n$/)
|
||||||
output.insert(chg.old_position, '<br>')
|
output.insert(chg.old_position, '<br>')
|
||||||
else
|
else
|
||||||
output.insert(chg.old_position, "#{escape_html[chg.new_element]}")
|
output.insert(chg.old_position, (escape_html[chg.new_element]).to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class UploadPreprocessorDelayedStartJob < ApplicationJob
|
class UploadPreprocessorDelayedStartJob < ApplicationJob
|
||||||
queue_as :default
|
queue_as :default
|
||||||
queue_with_priority -1
|
queue_with_priority(-1)
|
||||||
|
|
||||||
def perform(source, referer_url, uploader)
|
def perform(source, referer_url, uploader)
|
||||||
UploadService::Preprocessor.new(source: source, referer_url: referer_url).delayed_start(uploader.id)
|
UploadService::Preprocessor.new(source: source, referer_url: referer_url).delayed_start(uploader.id)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class UploadServiceDelayedStartJob < ApplicationJob
|
class UploadServiceDelayedStartJob < ApplicationJob
|
||||||
queue_as :default
|
queue_as :default
|
||||||
queue_with_priority -1
|
queue_with_priority(-1)
|
||||||
|
|
||||||
def perform(uploader)
|
def perform(uploader)
|
||||||
UploadService.delayed_start(uploader.id)
|
UploadService.delayed_start(uploader.id)
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class APNGInspector
|
|||||||
# Any data after chunk named IEND is irrelevant
|
# Any data after chunk named IEND is irrelevant
|
||||||
# APNG frame count is inside a chunk named acTL, in first 4 bytes of data.
|
# APNG frame count is inside a chunk named acTL, in first 4 bytes of data.
|
||||||
|
|
||||||
|
|
||||||
# This function calls associated block for each PNG chunk
|
# This function calls associated block for each PNG chunk
|
||||||
# parameters passed are |chunk_name, chunk_length, file_descriptor|
|
# parameters passed are |chunk_name, chunk_length, file_descriptor|
|
||||||
# returns true if file is read succesfully from start to IEND,
|
# returns true if file is read succesfully from start to IEND,
|
||||||
@@ -38,7 +37,7 @@ class APNGInspector
|
|||||||
chunkheader = ''
|
chunkheader = ''
|
||||||
while file.read(8, chunkheader)
|
while file.read(8, chunkheader)
|
||||||
# ensure that first 8 bytes from chunk were read properly
|
# ensure that first 8 bytes from chunk were read properly
|
||||||
if chunkheader == nil || chunkheader.length < 8
|
if chunkheader.nil? || chunkheader.length < 8
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -103,10 +102,9 @@ class APNGInspector
|
|||||||
def parse_actl(len, file)
|
def parse_actl(len, file)
|
||||||
return -1 if len != 8
|
return -1 if len != 8
|
||||||
framedata = file.read(4)
|
framedata = file.read(4)
|
||||||
if framedata == nil || framedata.length != 4
|
if framedata.nil? || framedata.length != 4
|
||||||
return -1
|
return -1
|
||||||
end
|
end
|
||||||
return framedata.unpack("N".freeze)[0]
|
return framedata.unpack1("N".freeze)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module ApproverPruner
|
module ApproverPruner
|
||||||
extend self
|
module_function
|
||||||
|
|
||||||
def inactive_approvers
|
def inactive_approvers
|
||||||
User.where("bit_prefs & ? > 0", User.flag_value_for("can_approve_posts")).select do |user|
|
User.where("bit_prefs & ? > 0", User.flag_value_for("can_approve_posts")).select do |user|
|
||||||
|
|||||||
@@ -64,15 +64,12 @@ class DText
|
|||||||
def self.parse_embedded_tag_request_text(text)
|
def self.parse_embedded_tag_request_text(text)
|
||||||
[TagAlias, TagImplication, BulkUpdateRequest].each do |tag_request|
|
[TagAlias, TagImplication, BulkUpdateRequest].each do |tag_request|
|
||||||
text = text.gsub(tag_request.embedded_pattern) do |match|
|
text = text.gsub(tag_request.embedded_pattern) do |match|
|
||||||
begin
|
|
||||||
obj = tag_request.find($~[:id])
|
obj = tag_request.find($~[:id])
|
||||||
tag_request_message(obj) || match
|
tag_request_message(obj) || match
|
||||||
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
match
|
match
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
text
|
text
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module DanbooruImageResizer
|
module DanbooruImageResizer
|
||||||
extend self
|
module_function
|
||||||
|
|
||||||
# Taken from ArgyllCMS 2.0.0 (see also: https://ninedegreesbelow.com/photography/srgb-profile-comparison.html)
|
# Taken from ArgyllCMS 2.0.0 (see also: https://ninedegreesbelow.com/photography/srgb-profile-comparison.html)
|
||||||
SRGB_PROFILE = "#{Rails.root}/config/sRGB.icm"
|
SRGB_PROFILE = "#{Rails.root}/config/sRGB.icm"
|
||||||
@@ -46,7 +46,6 @@ module DanbooruImageResizer
|
|||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
ensure
|
ensure
|
||||||
temp.close
|
temp.close
|
||||||
temp.unlink
|
temp.unlink
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class DanbooruLogger
|
|||||||
::NewRelic::Agent.add_custom_attributes(attributes)
|
::NewRelic::Agent.add_custom_attributes(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private_class_method
|
||||||
|
|
||||||
# flatten_hash({ foo: { bar: { baz: 42 } } })
|
# flatten_hash({ foo: { bar: { baz: 42 } } })
|
||||||
# => { "foo.bar.baz" => 42 }
|
# => { "foo.bar.baz" => 42 }
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# API requests must send a user agent and must use gzip compression, otherwise
|
# API requests must send a user agent and must use gzip compression, otherwise
|
||||||
# 403 errors will be returned.
|
# 403 errors will be returned.
|
||||||
|
|
||||||
class DeviantArtApiClient < Struct.new(:deviation_id)
|
DeviantArtApiClient = Struct.new(:deviation_id) do
|
||||||
extend Memoist
|
extend Memoist
|
||||||
|
|
||||||
def extended_fetch
|
def extended_fetch
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ module Downloads
|
|||||||
else
|
else
|
||||||
raise Error.new("HTTP error code: #{res.code} #{res.message}")
|
raise Error.new("HTTP error code: #{res.code} #{res.message}")
|
||||||
end
|
end
|
||||||
end # def
|
end
|
||||||
|
|
||||||
# Prevent Cloudflare from potentially mangling the image. See issue #3528.
|
# Prevent Cloudflare from potentially mangling the image. See issue #3528.
|
||||||
def uncached_url
|
def uncached_url
|
||||||
@@ -87,7 +87,7 @@ module Downloads
|
|||||||
timeout: 10,
|
timeout: 10,
|
||||||
stream_body: true,
|
stream_body: true,
|
||||||
headers: strategy.headers,
|
headers: strategy.headers,
|
||||||
connection_adapter: ValidatingConnectionAdapter,
|
connection_adapter: ValidatingConnectionAdapter
|
||||||
}.deep_merge(Danbooru.config.httparty_options)
|
}.deep_merge(Danbooru.config.httparty_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ module Moderator
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def search_by_ip_addr(ip_addrs)
|
def search_by_ip_addr(ip_addrs)
|
||||||
sums = Hash.new {|h, k| h[k] = 0}
|
sums = Hash.new {|h, k| h[k] = 0}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class NicoSeigaApiClient
|
|||||||
|
|
||||||
def get(url)
|
def get(url)
|
||||||
response = Danbooru::Http.cache(1.minute).get(url)
|
response = Danbooru::Http.cache(1.minute).get(url)
|
||||||
raise "nico seiga api call failed (code=#{response.code}, body=#{response.body.to_s})" if response.code != 200
|
raise "nico seiga api call failed (code=#{response.code}, body=#{response.body})" if response.code != 200
|
||||||
|
|
||||||
Hash.from_xml(response.to_s)
|
Hash.from_xml(response.to_s)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class NicoSeigaMangaApiClient
|
|||||||
|
|
||||||
def get(url)
|
def get(url)
|
||||||
response = Danbooru::Http.cache(1.minute).get(url)
|
response = Danbooru::Http.cache(1.minute).get(url)
|
||||||
raise "nico seiga api call failed (code=#{response.code}, body=#{response.body.to_s})" if response.code != 200
|
raise "nico seiga api call failed (code=#{response.code}, body=#{response.body})" if response.code != 200
|
||||||
|
|
||||||
Hash.from_xml(response.to_s)
|
Hash.from_xml(response.to_s)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module NoteSanitizer
|
|||||||
"span" => %w(class),
|
"span" => %w(class),
|
||||||
"div" => %w(class align),
|
"div" => %w(class align),
|
||||||
"p" => %w(class align),
|
"p" => %w(class align),
|
||||||
"font" => %w(color size),
|
"font" => %w(color size)
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOWED_PROPERTIES = %w(
|
ALLOWED_PROPERTIES = %w(
|
||||||
@@ -61,7 +61,7 @@ module NoteSanitizer
|
|||||||
:elements => ALLOWED_ELEMENTS,
|
:elements => ALLOWED_ELEMENTS,
|
||||||
:attributes => ALLOWED_ATTRIBUTES,
|
:attributes => ALLOWED_ATTRIBUTES,
|
||||||
:add_attributes => {
|
:add_attributes => {
|
||||||
"a" => { "rel" => "external noreferrer nofollow" },
|
"a" => { "rel" => "external noreferrer nofollow" }
|
||||||
},
|
},
|
||||||
:protocols => {
|
:protocols => {
|
||||||
"a" => {
|
"a" => {
|
||||||
@@ -73,9 +73,9 @@ module NoteSanitizer
|
|||||||
allow_hacks: false,
|
allow_hacks: false,
|
||||||
at_rules: [],
|
at_rules: [],
|
||||||
protocols: [],
|
protocols: [],
|
||||||
properties: ALLOWED_PROPERTIES,
|
properties: ALLOWED_PROPERTIES
|
||||||
},
|
},
|
||||||
:transformers => method(:relativize_links),
|
:transformers => method(:relativize_links)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ class PixivApiClient
|
|||||||
memoize :pages
|
memoize :pages
|
||||||
|
|
||||||
public
|
public
|
||||||
|
|
||||||
PXIMG = %r!\Ahttps?://i\.pximg\.net/c/\d+x\d+_\d+/novel-cover-master/img/(?<timestamp>\d+/\d+/\d+/\d+/\d+/\d+)/(?<filename>\d+_[a-f0-9]+)_master\d+\.(?<ext>jpg|jpeg|png|gif)!i
|
PXIMG = %r!\Ahttps?://i\.pximg\.net/c/\d+x\d+_\d+/novel-cover-master/img/(?<timestamp>\d+/\d+/\d+/\d+/\d+/\d+)/(?<filename>\d+_[a-f0-9]+)_master\d+\.(?<ext>jpg|jpeg|png|gif)!i
|
||||||
|
|
||||||
def find_original(x)
|
def find_original(x)
|
||||||
@@ -177,11 +178,10 @@ class PixivApiClient
|
|||||||
elsif json["status"] == "failure" && json.dig("errors", "system", "message") =~ /対象のイラストは見つかりませんでした。/
|
elsif json["status"] == "failure" && json.dig("errors", "system", "message") =~ /対象のイラストは見つかりませんでした。/
|
||||||
raise BadIDError.new("Pixiv ##{illust_id} not found: work was deleted, made private, or ID is invalid.")
|
raise BadIDError.new("Pixiv ##{illust_id} not found: work was deleted, made private, or ID is invalid.")
|
||||||
else
|
else
|
||||||
raise Error.new("Pixiv API call failed (status=#{response.code} body=#{response.body.to_s})")
|
raise Error.new("Pixiv API call failed (status=#{response.code} body=#{response.body})")
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
raise Error.new("Pixiv API call failed (status=#{response.code} body=#{response.body.to_s})")
|
raise Error.new("Pixiv API call failed (status=#{response.code} body=#{response.body})")
|
||||||
end
|
end
|
||||||
|
|
||||||
def fanbox(fanbox_id)
|
def fanbox(fanbox_id)
|
||||||
@@ -228,14 +228,14 @@ class PixivApiClient
|
|||||||
headers = {
|
headers = {
|
||||||
"Referer": "http://www.pixiv.net",
|
"Referer": "http://www.pixiv.net",
|
||||||
"X-Client-Time": client_time,
|
"X-Client-Time": client_time,
|
||||||
"X-Client-Hash": client_hash,
|
"X-Client-Hash": client_hash
|
||||||
}
|
}
|
||||||
params = {
|
params = {
|
||||||
username: Danbooru.config.pixiv_login,
|
username: Danbooru.config.pixiv_login,
|
||||||
password: Danbooru.config.pixiv_password,
|
password: Danbooru.config.pixiv_password,
|
||||||
grant_type: "password",
|
grant_type: "password",
|
||||||
client_id: CLIENT_ID,
|
client_id: CLIENT_ID,
|
||||||
client_secret: CLIENT_SECRET,
|
client_secret: CLIENT_SECRET
|
||||||
}
|
}
|
||||||
url = "https://oauth.secure.pixiv.net/auth/token"
|
url = "https://oauth.secure.pixiv.net/auth/token"
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ class PixivUgoiraConverter
|
|||||||
Rails.logger.error "[write_webm][ffmpeg] #{line}"
|
Rails.logger.error "[write_webm][ffmpeg] #{line}"
|
||||||
end
|
end
|
||||||
Rails.logger.error "[write_webm] ******************************"
|
Rails.logger.error "[write_webm] ******************************"
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
mkvmerge_out, status = Open3.capture2e("mkvmerge -o #{write_path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
|
mkvmerge_out, status = Open3.capture2e("mkvmerge -o #{write_path} --webm --timecodes 0:#{tmpdir}/timecodes.tc #{tmpdir}/tmp.webm")
|
||||||
@@ -63,7 +62,6 @@ class PixivUgoiraConverter
|
|||||||
Rails.logger.error "[write_webm][mkvmerge] #{line}"
|
Rails.logger.error "[write_webm][mkvmerge] #{line}"
|
||||||
end
|
end
|
||||||
Rails.logger.error "[write_webm] ******************************"
|
Rails.logger.error "[write_webm] ******************************"
|
||||||
return
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class PixivWebAgent
|
|||||||
COMIC_SESSION_COOKIE_KEY = "_pixiv-comic_session"
|
COMIC_SESSION_COOKIE_KEY = "_pixiv-comic_session"
|
||||||
|
|
||||||
def self.phpsessid(agent)
|
def self.phpsessid(agent)
|
||||||
agent.cookies.select do |cookie| cookie.name == SESSION_COOKIE_KEY end.first.try(:value)
|
agent.cookies.select { |cookie| cookie.name == SESSION_COOKIE_KEY }.first.try(:value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.build
|
def self.build
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class PopularSearchService
|
|||||||
JSON.parse(fetch_data.to_s).map {|x| x[0]}
|
JSON.parse(fetch_data.to_s).map {|x| x[0]}
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_data()
|
def fetch_data
|
||||||
return [] unless self.class.enabled?
|
return [] unless self.class.enabled?
|
||||||
|
|
||||||
dates = date.strftime("%Y-%m-%d")
|
dates = date.strftime("%Y-%m-%d")
|
||||||
@@ -54,8 +54,7 @@ class PopularSearchService
|
|||||||
end
|
end
|
||||||
|
|
||||||
data
|
data
|
||||||
|
rescue StandardError => e
|
||||||
rescue => e
|
|
||||||
DanbooruLogger.log(e)
|
DanbooruLogger.log(e)
|
||||||
return []
|
return []
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,14 +10,12 @@ protected
|
|||||||
def prune_pending!
|
def prune_pending!
|
||||||
CurrentUser.scoped(User.system, "127.0.0.1") do
|
CurrentUser.scoped(User.system, "127.0.0.1") do
|
||||||
Post.where("is_deleted = ? and is_pending = ? and created_at < ?", false, true, 3.days.ago).each do |post|
|
Post.where("is_deleted = ? and is_pending = ? and created_at < ?", false, true, 3.days.ago).each do |post|
|
||||||
begin
|
|
||||||
post.delete!("Unapproved in three days")
|
post.delete!("Unapproved in three days")
|
||||||
rescue PostFlag::Error
|
rescue PostFlag::Error
|
||||||
# swallow
|
# swallow
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def prune_flagged!
|
def prune_flagged!
|
||||||
CurrentUser.scoped(User.system, "127.0.0.1") do
|
CurrentUser.scoped(User.system, "127.0.0.1") do
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ class PostQueryBuilder
|
|||||||
if q[:flagger_ids_neg]
|
if q[:flagger_ids_neg]
|
||||||
q[:flagger_ids_neg].each do |flagger_id|
|
q[:flagger_ids_neg].each do |flagger_id|
|
||||||
if CurrentUser.can_view_flagger?(flagger_id)
|
if CurrentUser.can_view_flagger?(flagger_id)
|
||||||
post_ids = PostFlag.unscoped.search({:creator_id => flagger_id, :category => "normal"}).reorder("").select {|flag| flag.not_uploaded_by?(CurrentUser.id)}.map {|flag| flag.post_id}.uniq
|
post_ids = PostFlag.unscoped.search(:creator_id => flagger_id, :category => "normal").reorder("").select {|flag| flag.not_uploaded_by?(CurrentUser.id)}.map {|flag| flag.post_id}.uniq
|
||||||
if post_ids.any?
|
if post_ids.any?
|
||||||
relation = relation.where.not("posts.id": post_ids)
|
relation = relation.where.not("posts.id": post_ids)
|
||||||
end
|
end
|
||||||
@@ -310,11 +310,11 @@ class PostQueryBuilder
|
|||||||
if q[:flagger_ids]
|
if q[:flagger_ids]
|
||||||
q[:flagger_ids].each do |flagger_id|
|
q[:flagger_ids].each do |flagger_id|
|
||||||
if flagger_id == "any"
|
if flagger_id == "any"
|
||||||
relation = relation.where('EXISTS (' + PostFlag.unscoped.search({:category => "normal"}).where('post_id = posts.id').reorder('').select('1').to_sql + ')')
|
relation = relation.where('EXISTS (' + PostFlag.unscoped.search(:category => "normal").where('post_id = posts.id').reorder('').select('1').to_sql + ')')
|
||||||
elsif flagger_id == "none"
|
elsif flagger_id == "none"
|
||||||
relation = relation.where('NOT EXISTS (' + PostFlag.unscoped.search({:category => "normal"}).where('post_id = posts.id').reorder('').select('1').to_sql + ')')
|
relation = relation.where('NOT EXISTS (' + PostFlag.unscoped.search(:category => "normal").where('post_id = posts.id').reorder('').select('1').to_sql + ')')
|
||||||
elsif CurrentUser.can_view_flagger?(flagger_id)
|
elsif CurrentUser.can_view_flagger?(flagger_id)
|
||||||
post_ids = PostFlag.unscoped.search({:creator_id => flagger_id, :category => "normal"}).reorder("").select {|flag| flag.not_uploaded_by?(CurrentUser.id)}.map {|flag| flag.post_id}.uniq
|
post_ids = PostFlag.unscoped.search(:creator_id => flagger_id, :category => "normal").reorder("").select {|flag| flag.not_uploaded_by?(CurrentUser.id)}.map {|flag| flag.post_id}.uniq
|
||||||
relation = relation.where("posts.id": post_ids)
|
relation = relation.where("posts.id": post_ids)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ module PostSets
|
|||||||
end
|
end
|
||||||
|
|
||||||
def hidden_posts
|
def hidden_posts
|
||||||
posts.select { |p| !p.visible? }
|
posts.reject { |p| p.visible? }
|
||||||
end
|
end
|
||||||
|
|
||||||
def banned_posts
|
def banned_posts
|
||||||
@@ -122,17 +122,17 @@ module PostSets
|
|||||||
|
|
||||||
def posts
|
def posts
|
||||||
@posts ||= begin
|
@posts ||= begin
|
||||||
@post_count = get_post_count()
|
@post_count = get_post_count
|
||||||
|
|
||||||
if is_random?
|
if is_random?
|
||||||
temp = get_random_posts()
|
temp = get_random_posts
|
||||||
elsif raw
|
elsif raw
|
||||||
temp = ::Post.raw_tag_match(tag_string).order("posts.id DESC").where("true /* PostSets::Post#posts:1 */").paginate(page, :count => post_count, :limit => per_page)
|
temp = ::Post.raw_tag_match(tag_string).order("posts.id DESC").where("true /* PostSets::Post#posts:1 */").paginate(page, :count => post_count, :limit => per_page)
|
||||||
else
|
else
|
||||||
temp = ::Post.tag_match(tag_string).where("true /* PostSets::Post#posts:2 */").paginate(page, :count => post_count, :limit => per_page)
|
temp = ::Post.tag_match(tag_string).where("true /* PostSets::Post#posts:2 */").paginate(page, :count => post_count, :limit => per_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
# XXX HACK: uploader_name is needed in api responses and in data-uploader attribs (visible to mods only).
|
# HACK: uploader_name is needed in api responses and in data-uploader attribs (visible to mods only).
|
||||||
temp = temp.includes(:uploader) if !is_random? && (format.to_sym != :html || CurrentUser.is_moderator?)
|
temp = temp.includes(:uploader) if !is_random? && (format.to_sym != :html || CurrentUser.is_moderator?)
|
||||||
|
|
||||||
temp.each # hack to force rails to eager load
|
temp.each # hack to force rails to eager load
|
||||||
@@ -159,11 +159,11 @@ module PostSets
|
|||||||
end
|
end
|
||||||
|
|
||||||
def is_empty_tag?
|
def is_empty_tag?
|
||||||
tag_array.size == 0
|
tag_array.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_pattern_search?
|
def is_pattern_search?
|
||||||
is_single_tag? && tag_string =~ /\*/ && !tag_array.any? {|x| x =~ /^-?source:.+/}
|
is_single_tag? && tag_string =~ /\*/ && tag_array.none? {|x| x =~ /^-?source:.+/}
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_page
|
def current_page
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module RelatedTagCalculator
|
|||||||
tags = frequent_tags_for_search(tag_query, search_sample_size: search_sample_size, category: category).limit(tag_sample_size)
|
tags = frequent_tags_for_search(tag_query, search_sample_size: search_sample_size, category: category).limit(tag_sample_size)
|
||||||
tags = tags.sort_by do |tag|
|
tags = tags.sort_by do |tag|
|
||||||
# cosine distance(tag1, tag2) = 1 - {{tag1 tag2}} / sqrt({{tag1}} * {{tag2}})
|
# cosine distance(tag1, tag2) = 1 - {{tag1 tag2}} / sqrt({{tag1}} * {{tag2}})
|
||||||
1 - tag.overlap_count / (Math.sqrt(tag.post_count * search_count.to_f))
|
1 - tag.overlap_count / Math.sqrt(tag.post_count * search_count.to_f)
|
||||||
end
|
end
|
||||||
|
|
||||||
tags
|
tags
|
||||||
|
|||||||
@@ -47,6 +47,5 @@ module Reports
|
|||||||
def removed_tags
|
def removed_tags
|
||||||
removed_tags_array.join(' ')
|
removed_tags_array.join(' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,6 +30,6 @@ class SetDiff
|
|||||||
distance = ->(other) { ::DidYouMean::Levenshtein.distance(string, other) }
|
distance = ->(other) { ::DidYouMean::Levenshtein.distance(string, other) }
|
||||||
max_distance = string.size * max_dissimilarity
|
max_distance = string.size * max_dissimilarity
|
||||||
|
|
||||||
candidates.select { |candidate| distance[candidate] <= max_distance }.sort_by(&distance).first
|
candidates.select { |candidate| distance[candidate] <= max_distance }.min_by(&distance)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module Sources
|
|||||||
Strategies::ArtStation,
|
Strategies::ArtStation,
|
||||||
Strategies::Nijie,
|
Strategies::Nijie,
|
||||||
Strategies::Pawoo,
|
Strategies::Pawoo,
|
||||||
Strategies::Moebooru,
|
Strategies::Moebooru
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ module Sources::Strategies
|
|||||||
|
|
||||||
ASSET = %r!\Ahttps?://cdn\w*\.artstation\.com/p/assets/images/images/\d+/\d+/\d+/(?:medium|small|large)/!i
|
ASSET = %r!\Ahttps?://cdn\w*\.artstation\.com/p/assets/images/images/\d+/\d+/\d+/(?:medium|small|large)/!i
|
||||||
|
|
||||||
attr_reader :json, :image_urls
|
attr_reader :json
|
||||||
|
|
||||||
def domains
|
def domains
|
||||||
["artstation.com"]
|
["artstation.com"]
|
||||||
@@ -38,13 +38,11 @@ module Sources::Strategies
|
|||||||
end
|
end
|
||||||
|
|
||||||
def image_urls
|
def image_urls
|
||||||
image_urls_sub
|
@image_urls ||= image_urls_sub.map { |asset| original_asset_url(asset) }
|
||||||
.map { |asset| original_asset_url(asset) }
|
|
||||||
end
|
end
|
||||||
memoize :image_urls
|
|
||||||
|
|
||||||
def page_url
|
def page_url
|
||||||
return nil unless project_id.present?
|
return nil if project_id.blank?
|
||||||
|
|
||||||
if artist_name.present?
|
if artist_name.present?
|
||||||
"https://#{artist_name}.artstation.com/projects/#{project_id}"
|
"https://#{artist_name}.artstation.com/projects/#{project_id}"
|
||||||
@@ -54,7 +52,7 @@ module Sources::Strategies
|
|||||||
end
|
end
|
||||||
|
|
||||||
def profile_url
|
def profile_url
|
||||||
return nil unless artist_name.present?
|
return nil if artist_name.blank?
|
||||||
"https://www.artstation.com/#{artist_name}"
|
"https://www.artstation.com/#{artist_name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -84,14 +82,13 @@ module Sources::Strategies
|
|||||||
profile_url.present? && url == profile_url
|
profile_url.present? && url == profile_url
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def image_urls_sub
|
def image_urls_sub
|
||||||
if url.match?(ASSET)
|
if url.match?(ASSET)
|
||||||
return [url]
|
return [url]
|
||||||
end
|
end
|
||||||
|
|
||||||
api_response[:assets].to_a
|
api_response[:assets]
|
||||||
|
.to_a
|
||||||
.select { |asset| asset[:asset_type] == "image" }
|
.select { |asset| asset[:asset_type] == "image" }
|
||||||
.map { |asset| asset[:image_url] }
|
.map { |asset| asset[:image_url] }
|
||||||
end
|
end
|
||||||
@@ -108,7 +105,7 @@ module Sources::Strategies
|
|||||||
end
|
end
|
||||||
|
|
||||||
def api_response
|
def api_response
|
||||||
return {} unless project_id.present?
|
return {} if project_id.blank?
|
||||||
|
|
||||||
resp = Danbooru::Http.cache(1.minute).get("https://www.artstation.com/projects/#{project_id}.json")
|
resp = Danbooru::Http.cache(1.minute).get("https://www.artstation.com/projects/#{project_id}.json")
|
||||||
return {} if resp.code != 200
|
return {} if resp.code != 200
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ module Sources
|
|||||||
:tag_name => tag_name,
|
:tag_name => tag_name,
|
||||||
:other_names => other_names,
|
:other_names => other_names,
|
||||||
:profile_url => profile_url,
|
:profile_url => profile_url,
|
||||||
:profile_urls => profile_urls,
|
:profile_urls => profile_urls
|
||||||
},
|
},
|
||||||
:artists => artists.as_json(include: :sorted_urls),
|
:artists => artists.as_json(include: :sorted_urls),
|
||||||
:image_url => image_url,
|
:image_url => image_url,
|
||||||
@@ -284,18 +284,16 @@ module Sources
|
|||||||
:title => artist_commentary_title,
|
:title => artist_commentary_title,
|
||||||
:description => artist_commentary_desc,
|
:description => artist_commentary_desc,
|
||||||
:dtext_title => dtext_artist_commentary_title,
|
:dtext_title => dtext_artist_commentary_title,
|
||||||
:dtext_description => dtext_artist_commentary_desc,
|
:dtext_description => dtext_artist_commentary_desc
|
||||||
},
|
},
|
||||||
:api_response => api_response.to_h,
|
:api_response => api_response.to_h
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json
|
def to_json(*_args)
|
||||||
to_h.to_json
|
to_h.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def http_exists?(url, headers)
|
def http_exists?(url, headers)
|
||||||
res = HTTParty.head(url, Danbooru.config.httparty_options.deep_merge(headers: headers))
|
res = HTTParty.head(url, Danbooru.config.httparty_options.deep_merge(headers: headers))
|
||||||
res.success?
|
res.success?
|
||||||
@@ -306,7 +304,7 @@ module Sources
|
|||||||
def self.to_dtext(text)
|
def self.to_dtext(text)
|
||||||
text = text.to_s
|
text = text.to_s
|
||||||
text = Rails::Html::FullSanitizer.new.sanitize(text, encode_special_chars: false)
|
text = Rails::Html::FullSanitizer.new.sanitize(text, encode_special_chars: false)
|
||||||
text = CGI::unescapeHTML(text)
|
text = CGI.unescapeHTML(text)
|
||||||
text
|
text
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ module Sources
|
|||||||
PATH_PROFILE = %r{\Ahttps?://(www\.)?deviantart\.com/#{ARTIST}/?\z}i
|
PATH_PROFILE = %r{\Ahttps?://(www\.)?deviantart\.com/#{ARTIST}/?\z}i
|
||||||
SUBDOMAIN_PROFILE = %r{\Ahttps?://#{ARTIST}\.deviantart\.com/?\z}i
|
SUBDOMAIN_PROFILE = %r{\Ahttps?://#{ARTIST}\.deviantart\.com/?\z}i
|
||||||
|
|
||||||
attr_accessor :api_client
|
|
||||||
|
|
||||||
def domains
|
def domains
|
||||||
["deviantart.net", "deviantart.com"]
|
["deviantart.net", "deviantart.com"]
|
||||||
end
|
end
|
||||||
@@ -211,8 +209,6 @@ module Sources
|
|||||||
end.gsub(/\A[[:space:]]+|[[:space:]]+\z/, "")
|
end.gsub(/\A[[:space:]]+|[[:space:]]+\z/, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def self.deviation_id_from_url(url)
|
def self.deviation_id_from_url(url)
|
||||||
if url =~ ASSET
|
if url =~ ASSET
|
||||||
$~[:base36_deviation_id].try(:to_i, 36)
|
$~[:base36_deviation_id].try(:to_i, 36)
|
||||||
|
|||||||
@@ -130,8 +130,6 @@ module Sources
|
|||||||
end
|
end
|
||||||
memoize :tags
|
memoize :tags
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def api_client
|
def api_client
|
||||||
if illust_id
|
if illust_id
|
||||||
NicoSeigaApiClient.new(illust_id: illust_id)
|
NicoSeigaApiClient.new(illust_id: illust_id)
|
||||||
|
|||||||
@@ -120,9 +120,11 @@ module Sources
|
|||||||
def tags
|
def tags
|
||||||
links = page&.search("div#view-tag a") || []
|
links = page&.search("div#view-tag a") || []
|
||||||
|
|
||||||
links.select do |node|
|
search_links = links.select do |node|
|
||||||
node["href"] =~ /search\.php/
|
node["href"] =~ /search\.php/
|
||||||
end.map do |node|
|
end
|
||||||
|
|
||||||
|
search_links.map do |node|
|
||||||
[node.inner_text, "https://nijie.info" + node.attr("href")]
|
[node.inner_text, "https://nijie.info" + node.attr("href")]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -131,8 +133,6 @@ module Sources
|
|||||||
"nijie" + artist_id.to_s
|
"nijie" + artist_id.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def self.to_dtext(text)
|
def self.to_dtext(text)
|
||||||
text = text.to_s.gsub(/\r\n|\r/, "<br>")
|
text = text.to_s.gsub(/\r\n|\r/, "<br>")
|
||||||
DText.from_html(text).strip
|
DText.from_html(text).strip
|
||||||
@@ -207,7 +207,6 @@ module Sources
|
|||||||
mech.cookie_jar.add(cookie)
|
mech.cookie_jar.add(cookie)
|
||||||
|
|
||||||
mech
|
mech
|
||||||
|
|
||||||
rescue Mechanize::ResponseCodeError => x
|
rescue Mechanize::ResponseCodeError => x
|
||||||
if x.response_code.to_i == 429
|
if x.response_code.to_i == 429
|
||||||
sleep(5)
|
sleep(5)
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ module Sources::Strategies
|
|||||||
end.strip
|
end.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def api_response
|
def api_response
|
||||||
[url, referer_url].each do |x|
|
[url, referer_url].each do |x|
|
||||||
if client = PawooApiClient.new.get(x)
|
if client = PawooApiClient.new.get(x)
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ module Sources
|
|||||||
end
|
end
|
||||||
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
rescue PixivApiClient::BadIDError
|
rescue PixivApiClient::BadIDError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
@@ -236,8 +235,6 @@ module Sources
|
|||||||
illust_id.present? ? "pixiv:#{illust_id}" : "source:#{canonical_url}"
|
illust_id.present? ? "pixiv:#{illust_id}" : "source:#{canonical_url}"
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def image_urls_sub
|
def image_urls_sub
|
||||||
if url =~ FANBOX_IMAGE
|
if url =~ FANBOX_IMAGE
|
||||||
return [url]
|
return [url]
|
||||||
|
|||||||
@@ -131,8 +131,6 @@ module Sources::Strategies
|
|||||||
DText.from_html(artist_commentary_desc).strip
|
DText.from_html(artist_commentary_desc).strip
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
# Look for the biggest available version on media.tumblr.com. A bigger
|
# Look for the biggest available version on media.tumblr.com. A bigger
|
||||||
# version may or may not exist.
|
# version may or may not exist.
|
||||||
#
|
#
|
||||||
@@ -181,7 +179,7 @@ module Sources::Strategies
|
|||||||
|
|
||||||
response = Danbooru::Http.cache(1.minute).get(
|
response = Danbooru::Http.cache(1.minute).get(
|
||||||
"https://api.tumblr.com/v2/blog/#{blog_name}/posts",
|
"https://api.tumblr.com/v2/blog/#{blog_name}/posts",
|
||||||
params: { id: post_id, api_key: Danbooru.config.tumblr_consumer_key },
|
params: { id: post_id, api_key: Danbooru.config.tumblr_consumer_key }
|
||||||
)
|
)
|
||||||
|
|
||||||
return {} if response.code != 200
|
return {} if response.code != 200
|
||||||
|
|||||||
@@ -134,15 +134,13 @@ module Sources::Strategies
|
|||||||
url_replacements = url_replacements.to_h
|
url_replacements = url_replacements.to_h
|
||||||
|
|
||||||
desc = artist_commentary_desc.unicode_normalize(:nfkc)
|
desc = artist_commentary_desc.unicode_normalize(:nfkc)
|
||||||
desc = CGI::unescapeHTML(desc)
|
desc = CGI.unescapeHTML(desc)
|
||||||
desc = desc.gsub(%r!https?://t\.co/[a-zA-Z0-9]+!i, url_replacements)
|
desc = desc.gsub(%r!https?://t\.co/[a-zA-Z0-9]+!i, url_replacements)
|
||||||
desc = desc.gsub(%r!#([^[:space:]]+)!, '"#\\1":[https://twitter.com/hashtag/\\1]')
|
desc = desc.gsub(%r!#([^[:space:]]+)!, '"#\\1":[https://twitter.com/hashtag/\\1]')
|
||||||
desc = desc.gsub(%r!@([a-zA-Z0-9_]+)!, '"@\\1":[https://twitter.com/\\1]')
|
desc = desc.gsub(%r!@([a-zA-Z0-9_]+)!, '"@\\1":[https://twitter.com/\\1]')
|
||||||
desc.strip
|
desc.strip
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
|
||||||
|
|
||||||
def api_client
|
def api_client
|
||||||
TwitterApiClient.new(Danbooru.config.twitter_api_key, Danbooru.config.twitter_api_secret)
|
TwitterApiClient.new(Danbooru.config.twitter_api_key, Danbooru.config.twitter_api_secret)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class SpamDetector
|
|||||||
# rakismet raises an exception if the api key or url aren't configured
|
# rakismet raises an exception if the api key or url aren't configured
|
||||||
def self.working?
|
def self.working?
|
||||||
Rakismet.validate_key
|
Rakismet.validate_key
|
||||||
rescue
|
rescue StandardError
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class SpamDetector
|
|||||||
end
|
end
|
||||||
|
|
||||||
is_spam
|
is_spam
|
||||||
rescue => exception
|
rescue StandardError => exception
|
||||||
DanbooruLogger.log(exception)
|
DanbooruLogger.log(exception)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class SqsService
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def sqs
|
def sqs
|
||||||
@sqs ||= Aws::SQS::Client.new(
|
@sqs ||= Aws::SQS::Client.new(
|
||||||
credentials: Danbooru.config.aws_credentials,
|
credentials: Danbooru.config.aws_credentials,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class StorageManager
|
|||||||
end
|
end
|
||||||
|
|
||||||
def open_file(post, type)
|
def open_file(post, type)
|
||||||
open(file_path(post.md5, post.file_ext, type))
|
self.open(file_path(post.md5, post.file_ext, type))
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_url(post, type, tagged_filenames: false)
|
def file_url(post, type, tagged_filenames: false)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class StorageManager::Local < StorageManager
|
class StorageManager::Local < StorageManager
|
||||||
DEFAULT_PERMISSIONS = 0644
|
DEFAULT_PERMISSIONS = 0o644
|
||||||
|
|
||||||
def store(io, dest_path)
|
def store(io, dest_path)
|
||||||
temp_path = dest_path + "-" + SecureRandom.uuid + ".tmp"
|
temp_path = dest_path + "-" + SecureRandom.uuid + ".tmp"
|
||||||
|
|||||||
@@ -1,35 +1,33 @@
|
|||||||
=begin
|
#
|
||||||
|
# Generalizes the hybrid storage manager to be more declarative in
|
||||||
Generalizes the hybrid storage manager to be more declarative in
|
# syntax. Matches are executed in order of appearance so the first
|
||||||
syntax. Matches are executed in order of appearance so the first
|
# matching manager is returned. You should always add at least one
|
||||||
matching manager is returned. You should always add at least one
|
# manager with no constraints as a default case.
|
||||||
manager with no constraints as a default case.
|
#
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
#
|
||||||
StorageManager::Match.new do |matcher|
|
# StorageManager::Match.new do |matcher|
|
||||||
matcher.add_manager(type: :crop) do
|
# matcher.add_manager(type: :crop) do
|
||||||
StorageManager::SFTP.new("raikou3.donmai.us", base_url: "https://raikou3.donmai.us", hierarchical: true, base_dir: "/var/www/raikou3")
|
# StorageManager::SFTP.new("raikou3.donmai.us", base_url: "https://raikou3.donmai.us", hierarchical: true, base_dir: "/var/www/raikou3")
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
matcher.add_manager(id: 1..850_000) do
|
# matcher.add_manager(id: 1..850_000) do
|
||||||
StorageManager::SFTP.new("raikou1.donmai.us", base_url: "https://raikou1.donmai.us", hierarchical: true, base_dir: "/var/www/raikou1")
|
# StorageManager::SFTP.new("raikou1.donmai.us", base_url: "https://raikou1.donmai.us", hierarchical: true, base_dir: "/var/www/raikou1")
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
matcher.add_manager(id: 850_001..2_000_000) do
|
# matcher.add_manager(id: 850_001..2_000_000) do
|
||||||
StorageManager::SFTP.new("raikou2.donmai.us", base_url: "https://raikou2.donmai.us", hierarchical: true, base_dir: "/var/www/raikou2")
|
# StorageManager::SFTP.new("raikou2.donmai.us", base_url: "https://raikou2.donmai.us", hierarchical: true, base_dir: "/var/www/raikou2")
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
matcher.add_manager(id: 1..3_000_000, type: [:large, :original]) do
|
# matcher.add_manager(id: 1..3_000_000, type: [:large, :original]) do
|
||||||
StorageManager::SFTP.new(*Danbooru.config.all_server_hosts, base_url: "https://hijiribe.donmai.us/data")
|
# StorageManager::SFTP.new(*Danbooru.config.all_server_hosts, base_url: "https://hijiribe.donmai.us/data")
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
matcher.add_manager({}) do
|
# matcher.add_manager({}) do
|
||||||
StorageManager::SFTP.new(*Danbooru.config.all_server_hosts, base_url: "#{CurrentUser.root_url}/data")
|
# StorageManager::SFTP.new(*Danbooru.config.all_server_hosts, base_url: "#{CurrentUser.root_url}/data")
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
=end
|
|
||||||
|
|
||||||
class StorageManager::Match < StorageManager
|
class StorageManager::Match < StorageManager
|
||||||
def initialize
|
def initialize
|
||||||
@@ -109,4 +107,3 @@ class StorageManager::Match < StorageManager
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
class StorageManager::SFTP < StorageManager
|
class StorageManager::SFTP < StorageManager
|
||||||
DEFAULT_PERMISSIONS = 0644
|
DEFAULT_PERMISSIONS = 0o644
|
||||||
|
|
||||||
# http://net-ssh.github.io/net-ssh/Net/SSH.html#method-c-start
|
# http://net-ssh.github.io/net-ssh/Net/SSH.html#method-c-start
|
||||||
DEFAULT_SSH_OPTIONS = {
|
DEFAULT_SSH_OPTIONS = {
|
||||||
timeout: 10,
|
timeout: 10,
|
||||||
logger: Rails.logger,
|
logger: Rails.logger,
|
||||||
verbose: :fatal,
|
verbose: :fatal,
|
||||||
non_interactive: true,
|
non_interactive: true
|
||||||
}
|
}
|
||||||
|
|
||||||
attr_reader :hosts, :ssh_options
|
attr_reader :hosts, :ssh_options
|
||||||
@@ -22,7 +22,6 @@ class StorageManager::SFTP < StorageManager
|
|||||||
dest_backup_path = dest_path + "-" + SecureRandom.uuid + ".bak"
|
dest_backup_path = dest_path + "-" + SecureRandom.uuid + ".bak"
|
||||||
|
|
||||||
each_host do |host, sftp|
|
each_host do |host, sftp|
|
||||||
begin
|
|
||||||
sftp.upload!(file.path, temp_upload_path)
|
sftp.upload!(file.path, temp_upload_path)
|
||||||
sftp.setstat!(temp_upload_path, permissions: DEFAULT_PERMISSIONS)
|
sftp.setstat!(temp_upload_path, permissions: DEFAULT_PERMISSIONS)
|
||||||
|
|
||||||
@@ -39,7 +38,6 @@ class StorageManager::SFTP < StorageManager
|
|||||||
force { sftp.remove!(dest_backup_path) }
|
force { sftp.remove!(dest_backup_path) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def delete(dest_path)
|
def delete(dest_path)
|
||||||
each_host do |host, sftp|
|
each_host do |host, sftp|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
module TagAutocomplete
|
module TagAutocomplete
|
||||||
extend self
|
module_function
|
||||||
|
|
||||||
PREFIX_BOUNDARIES = "(_/:;-"
|
PREFIX_BOUNDARIES = "(_/:;-"
|
||||||
LIMIT = 10
|
LIMIT = 10
|
||||||
|
|
||||||
class Result < Struct.new(:name, :post_count, :category, :antecedent_name, :source)
|
Result = Struct.new(:name, :post_count, :category, :antecedent_name, :source) do
|
||||||
include ActiveModel::Serializers::JSON
|
include ActiveModel::Serializers::JSON
|
||||||
include ActiveModel::Serializers::Xml
|
include ActiveModel::Serializers::Xml
|
||||||
|
|
||||||
@@ -112,4 +112,3 @@ module TagAutocomplete
|
|||||||
.map {|row| Result.new(*row, :alias)}
|
.map {|row| Result.new(*row, :alias)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module TagChangeNoticeService
|
module TagChangeNoticeService
|
||||||
extend self
|
module_function
|
||||||
|
|
||||||
def get_forum_topic_id(tag)
|
def get_forum_topic_id(tag)
|
||||||
Cache.get("tcn:#{tag}")
|
Cache.get("tcn:#{tag}")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
module TagRelationshipRetirementService
|
module TagRelationshipRetirementService
|
||||||
THRESHOLD = 2.year
|
module_function
|
||||||
|
THRESHOLD = 2.years
|
||||||
extend self
|
|
||||||
|
|
||||||
def forum_topic_title
|
def forum_topic_title
|
||||||
return "Retired tag aliases & implications"
|
return "Retired tag aliases & implications"
|
||||||
|
|||||||
1
app/logical/upload_error_checker.rb
Normal file → Executable file
1
app/logical/upload_error_checker.rb
Normal file → Executable file
@@ -19,4 +19,3 @@ class UploadErrorChecker
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ class UploadService
|
|||||||
@upload.save!
|
@upload.save!
|
||||||
@post = create_post_from_upload(@upload)
|
@post = create_post_from_upload(@upload)
|
||||||
return @upload
|
return @upload
|
||||||
|
|
||||||
rescue Exception => x
|
rescue Exception => x
|
||||||
@upload.update(status: "error: #{x.class} - #{x.message}", backtrace: x.backtrace.join("\n"))
|
@upload.update(status: "error: #{x.class} - #{x.message}", backtrace: x.backtrace.join("\n"))
|
||||||
@upload
|
@upload
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ class UploadService
|
|||||||
CurrentUser.as(uploader_id) do
|
CurrentUser.as(uploader_id) do
|
||||||
start!
|
start!
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue ActiveRecord::RecordNotUnique
|
rescue ActiveRecord::RecordNotUnique
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -106,7 +105,7 @@ class UploadService
|
|||||||
end
|
end
|
||||||
|
|
||||||
def finish!(upload = nil)
|
def finish!(upload = nil)
|
||||||
pred = upload || self.predecessor()
|
pred = upload || self.predecessor
|
||||||
|
|
||||||
# regardless of who initialized the upload, credit should
|
# regardless of who initialized the upload, credit should
|
||||||
# goto whoever submitted the form
|
# goto whoever submitted the form
|
||||||
@@ -124,5 +123,4 @@ class UploadService
|
|||||||
return pred
|
return pred
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class UploadService
|
class UploadService
|
||||||
module Utils
|
module Utils
|
||||||
extend self
|
module_function
|
||||||
class CorruptFileError < RuntimeError; end
|
class CorruptFileError < RuntimeError; end
|
||||||
|
|
||||||
def file_header_to_file_ext(file)
|
def file_header_to_file_ext(file)
|
||||||
@@ -93,7 +93,7 @@ class UploadService
|
|||||||
|
|
||||||
def generate_video_crop_for(video, width)
|
def generate_video_crop_for(video, width)
|
||||||
vp = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
vp = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
||||||
video.screenshot(vp.path, {:seek_time => 0, :resolution => "#{video.width}x#{video.height}"})
|
video.screenshot(vp.path, :seek_time => 0, :resolution => "#{video.width}x#{video.height}")
|
||||||
crop = DanbooruImageResizer.crop(vp, width, width, 85)
|
crop = DanbooruImageResizer.crop(vp, width, width, 85)
|
||||||
vp.close
|
vp.close
|
||||||
return crop
|
return crop
|
||||||
@@ -108,7 +108,7 @@ class UploadService
|
|||||||
end
|
end
|
||||||
|
|
||||||
output_file = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
output_file = Tempfile.new(["video-preview", ".jpg"], binmode: true)
|
||||||
video.screenshot(output_file.path, {:seek_time => 0, :resolution => "#{width}x#{height}"})
|
video.screenshot(output_file.path, :seek_time => 0, :resolution => "#{width}x#{height}")
|
||||||
output_file
|
output_file
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ class UploadService
|
|||||||
|
|
||||||
def get_file_for_upload(upload, file: nil)
|
def get_file_for_upload(upload, file: nil)
|
||||||
return file if file.present?
|
return file if file.present?
|
||||||
raise RuntimeError, "No file or source URL provided" if upload.source_url.blank?
|
raise "No file or source URL provided" if upload.source_url.blank?
|
||||||
|
|
||||||
attempts = 0
|
attempts = 0
|
||||||
|
|
||||||
@@ -190,8 +190,7 @@ class UploadService
|
|||||||
if !DanbooruImageResizer.validate_shell(file)
|
if !DanbooruImageResizer.validate_shell(file)
|
||||||
raise CorruptFileError.new("File is corrupted")
|
raise CorruptFileError.new("File is corrupted")
|
||||||
end
|
end
|
||||||
|
rescue StandardError
|
||||||
rescue
|
|
||||||
if attempts == 3
|
if attempts == 3
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ private
|
|||||||
def rename
|
def rename
|
||||||
name = "user_#{user.id}"
|
name = "user_#{user.id}"
|
||||||
n = 0
|
n = 0
|
||||||
while User.where(:name => name).exists? && (n < 10)
|
name += "~" while User.where(:name => name).exists? && (n < 10)
|
||||||
name += "~"
|
|
||||||
end
|
|
||||||
|
|
||||||
if n == 10
|
if n == 10
|
||||||
raise ValidationError.new("New name could not be found")
|
raise ValidationError.new("New name could not be found")
|
||||||
|
|||||||
@@ -18,19 +18,19 @@ class UserPromotion
|
|||||||
|
|
||||||
user.level = new_level
|
user.level = new_level
|
||||||
|
|
||||||
if options.has_key?(:can_approve_posts)
|
if options.key?(:can_approve_posts)
|
||||||
user.can_approve_posts = options[:can_approve_posts]
|
user.can_approve_posts = options[:can_approve_posts]
|
||||||
end
|
end
|
||||||
|
|
||||||
if options.has_key?(:can_upload_free)
|
if options.key?(:can_upload_free)
|
||||||
user.can_upload_free = options[:can_upload_free]
|
user.can_upload_free = options[:can_upload_free]
|
||||||
end
|
end
|
||||||
|
|
||||||
if options.has_key?(:no_feedback)
|
if options.key?(:no_feedback)
|
||||||
user.no_feedback = options[:no_feedback]
|
user.no_feedback = options[:no_feedback]
|
||||||
end
|
end
|
||||||
|
|
||||||
if options.has_key?(:no_flagging)
|
if options.key?(:no_flagging)
|
||||||
user.no_flagging = options[:no_flagging]
|
user.no_flagging = options[:no_flagging]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ class Artist < ApplicationRecord
|
|||||||
"youtube.com/c", # https://www.youtube.com/c/serafleurArt
|
"youtube.com/c", # https://www.youtube.com/c/serafleurArt
|
||||||
"youtube.com/channel", # https://www.youtube.com/channel/UCfrCa2Y6VulwHD3eNd3HBRA
|
"youtube.com/channel", # https://www.youtube.com/channel/UCfrCa2Y6VulwHD3eNd3HBRA
|
||||||
"youtube.com/user", # https://www.youtube.com/user/148nasuka
|
"youtube.com/user", # https://www.youtube.com/user/148nasuka
|
||||||
"youtu.be", # http://youtu.be/gibeLKKRT-0
|
"youtu.be" # http://youtu.be/gibeLKKRT-0
|
||||||
]
|
]
|
||||||
|
|
||||||
SITE_BLACKLIST_REGEXP = Regexp.union(SITE_BLACKLIST.map do |domain|
|
SITE_BLACKLIST_REGEXP = Regexp.union(SITE_BLACKLIST.map do |domain|
|
||||||
@@ -213,13 +213,13 @@ class Artist < ApplicationRecord
|
|||||||
|
|
||||||
def domains
|
def domains
|
||||||
Cache.get("artist-domains-#{id}", 1.day) do
|
Cache.get("artist-domains-#{id}", 1.day) do
|
||||||
Post.raw_tag_match(name).pluck(:source).map do |x|
|
domains = Post.raw_tag_match(name).pluck(:source).map do |x|
|
||||||
begin
|
|
||||||
map_domain(Addressable::URI.parse(x).domain)
|
map_domain(Addressable::URI.parse(x).domain)
|
||||||
rescue Addressable::URI::InvalidURIError
|
rescue Addressable::URI::InvalidURIError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end.compact.inject(Hash.new(0)) {|h, x| h[x] += 1; h}.sort {|a, b| b[1] <=> a[1]}
|
|
||||||
|
domains.compact.inject(Hash.new(0)) {|h, x| h[x] += 1; h}.sort {|a, b| b[1] <=> a[1]}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -401,7 +401,7 @@ class Artist < ApplicationRecord
|
|||||||
Post.transaction do
|
Post.transaction do
|
||||||
CurrentUser.without_safe_mode do
|
CurrentUser.without_safe_mode do
|
||||||
ti = TagImplication.where(:antecedent_name => name, :consequent_name => "banned_artist").first
|
ti = TagImplication.where(:antecedent_name => name, :consequent_name => "banned_artist").first
|
||||||
ti.destroy if ti
|
ti&.destroy
|
||||||
|
|
||||||
Post.tag_match(name).where("true /* Artist.unban */").each do |post|
|
Post.tag_match(name).where("true /* Artist.unban */").each do |post|
|
||||||
post.unban!
|
post.unban!
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class ArtistCommentary < ApplicationRecord
|
|||||||
original_title: original_title,
|
original_title: original_title,
|
||||||
original_description: original_description,
|
original_description: original_description,
|
||||||
translated_title: translated_title,
|
translated_title: translated_title,
|
||||||
translated_description: translated_description,
|
translated_description: translated_description
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -94,9 +94,7 @@ class Ban < ApplicationRecord
|
|||||||
@duration = dur
|
@duration = dur
|
||||||
end
|
end
|
||||||
|
|
||||||
def duration
|
attr_reader :duration
|
||||||
@duration
|
|
||||||
end
|
|
||||||
|
|
||||||
def humanized_duration
|
def humanized_duration
|
||||||
ApplicationController.helpers.distance_of_time_in_words(created_at, expires_at)
|
ApplicationController.helpers.distance_of_time_in_words(created_at, expires_at)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
class BulkUpdateRequest < ApplicationRecord
|
class BulkUpdateRequest < ApplicationRecord
|
||||||
attr_accessor :reason, :skip_secondary_validations
|
attr_accessor :reason
|
||||||
|
attr_reader :skip_secondary_validations
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :forum_topic, optional: true
|
belongs_to :forum_topic, optional: true
|
||||||
@@ -81,11 +82,10 @@ class BulkUpdateRequest < ApplicationRecord
|
|||||||
forum_updater.update("The #{bulk_update_request_link} (forum ##{forum_post.id}) has been approved by @#{approver.name}.", "APPROVED")
|
forum_updater.update("The #{bulk_update_request_link} (forum ##{forum_post.id}) has been approved by @#{approver.name}.", "APPROVED")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue AliasAndImplicationImporter::Error => x
|
rescue AliasAndImplicationImporter::Error => x
|
||||||
self.approver = approver
|
self.approver = approver
|
||||||
CurrentUser.scoped(approver) do
|
CurrentUser.scoped(approver) do
|
||||||
forum_updater.update("The #{bulk_update_request_link} (forum ##{forum_post.id}) has failed: #{x.to_s}", "FAILED")
|
forum_updater.update("The #{bulk_update_request_link} (forum ##{forum_post.id}) has failed: #{x}", "FAILED")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -129,13 +129,11 @@ class BulkUpdateRequest < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_script
|
def validate_script
|
||||||
begin
|
|
||||||
AliasAndImplicationImporter.new(script, forum_topic_id, "1", skip_secondary_validations).validate!
|
AliasAndImplicationImporter.new(script, forum_topic_id, "1", skip_secondary_validations).validate!
|
||||||
rescue RuntimeError => e
|
rescue RuntimeError => e
|
||||||
errors[:base] << e.message
|
errors[:base] << e.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
extend SearchMethods
|
extend SearchMethods
|
||||||
include ApprovalMethods
|
include ApprovalMethods
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class Comment < ApplicationRecord
|
|||||||
mentionable(
|
mentionable(
|
||||||
:message_field => :body,
|
:message_field => :body,
|
||||||
:title => ->(user_name) {"#{creator.name} mentioned you in a comment on post ##{post_id}"},
|
:title => ->(user_name) {"#{creator.name} mentioned you in a comment on post ##{post_id}"},
|
||||||
:body => ->(user_name) {"@#{creator.name} mentioned you in a \"comment\":/posts/#{post_id}#comment-#{id} on post ##{post_id}:\n\n[quote]\n#{DText.excerpt(body, "@"+user_name)}\n[/quote]\n"},
|
:body => ->(user_name) {"@#{creator.name} mentioned you in a \"comment\":/posts/#{post_id}#comment-#{id} on post ##{post_id}:\n\n[quote]\n#{DText.excerpt(body, "@" + user_name)}\n[/quote]\n"}
|
||||||
)
|
)
|
||||||
|
|
||||||
api_attributes including: [:creator_name, :updater_name]
|
api_attributes including: [:creator_name, :updater_name]
|
||||||
@@ -56,7 +56,7 @@ class Comment < ApplicationRecord
|
|||||||
|
|
||||||
module VoteMethods
|
module VoteMethods
|
||||||
def vote!(val)
|
def vote!(val)
|
||||||
numerical_score = val == "up" ? 1 : -1
|
numerical_score = (val == "up") ? 1 : -1
|
||||||
vote = votes.create!(:score => numerical_score)
|
vote = votes.create!(:score => numerical_score)
|
||||||
|
|
||||||
if vote.is_positive?
|
if vote.is_positive?
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class DmailFilter < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def filtered?(dmail)
|
def filtered?(dmail)
|
||||||
dmail.from.level < User::Levels::MODERATOR && has_filter? && (dmail.body =~ regexp || dmail.title =~ regexp || dmail.from.name =~ regexp)
|
dmail.from.level < User::Levels::MODERATOR && has_filter? && (dmail.body.match?(regexp) || dmail.title.match?(regexp) || dmail.from.name.match?(regexp))
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_filter?
|
def has_filter?
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class Favorite < ApplicationRecord
|
|||||||
return unless Favorite.for_user(user.id).where(:user_id => user.id, :post_id => post_id).exists?
|
return unless Favorite.for_user(user.id).where(:user_id => user.id, :post_id => post_id).exists?
|
||||||
Favorite.for_user(user.id).where(post_id: post_id).delete_all
|
Favorite.for_user(user.id).where(post_id: post_id).delete_all
|
||||||
Post.where(:id => post_id).update_all("fav_count = fav_count - 1")
|
Post.where(:id => post_id).update_all("fav_count = fav_count - 1")
|
||||||
post.delete_user_from_fav_string(user.id) if post
|
post&.delete_user_from_fav_string(user.id)
|
||||||
User.where(:id => user.id).update_all("favorite_count = favorite_count - 1")
|
User.where(:id => user.id).update_all("favorite_count = favorite_count - 1")
|
||||||
user.favorite_count -= 1
|
user.favorite_count -= 1
|
||||||
post.fav_count -= 1 if post
|
post.fav_count -= 1 if post
|
||||||
|
|||||||
@@ -130,13 +130,11 @@ class FavoriteGroup < ApplicationRecord
|
|||||||
offset = options[:offset] || 0
|
offset = options[:offset] || 0
|
||||||
limit = options[:limit] || Danbooru.config.posts_per_page
|
limit = options[:limit] || Danbooru.config.posts_per_page
|
||||||
slice = post_id_array.slice(offset, limit)
|
slice = post_id_array.slice(offset, limit)
|
||||||
if slice && slice.any?
|
if slice&.any?
|
||||||
slice.map do |id|
|
slice.map do |id|
|
||||||
begin
|
|
||||||
Post.find(id)
|
Post.find(id)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
# swallow
|
# swallow
|
||||||
end
|
|
||||||
end.compact
|
end.compact
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class ForumPost < ApplicationRecord
|
|||||||
mentionable(
|
mentionable(
|
||||||
:message_field => :body,
|
:message_field => :body,
|
||||||
:title => ->(user_name) {%{#{creator.name} mentioned you in topic ##{topic_id} (#{topic.title})}},
|
:title => ->(user_name) {%{#{creator.name} mentioned you in topic ##{topic_id} (#{topic.title})}},
|
||||||
:body => ->(user_name) {%{@#{creator.name} mentioned you in topic ##{topic_id} ("#{topic.title}":[/forum_topics/#{topic_id}?page=#{forum_topic_page}]):\n\n[quote]\n#{DText.excerpt(body, "@"+user_name)}\n[/quote]\n}},
|
:body => ->(user_name) {%{@#{creator.name} mentioned you in topic ##{topic_id} ("#{topic.title}":[/forum_topics/#{topic_id}?page=#{forum_topic_page}]):\n\n[quote]\n#{DText.excerpt(body, "@" + user_name)}\n[/quote]\n}}
|
||||||
)
|
)
|
||||||
|
|
||||||
module SearchMethods
|
module SearchMethods
|
||||||
@@ -173,11 +173,11 @@ class ForumPost < ApplicationRecord
|
|||||||
max = ForumPost.where(:topic_id => topic.id, :is_deleted => false).order("updated_at desc").first
|
max = ForumPost.where(:topic_id => topic.id, :is_deleted => false).order("updated_at desc").first
|
||||||
if max
|
if max
|
||||||
ForumTopic.where(:id => topic.id).update_all(["response_count = response_count - 1, updated_at = ?, updater_id = ?", max.updated_at, max.updater_id])
|
ForumTopic.where(:id => topic.id).update_all(["response_count = response_count - 1, updated_at = ?, updater_id = ?", max.updated_at, max.updater_id])
|
||||||
topic.response_count -= 1
|
|
||||||
else
|
else
|
||||||
ForumTopic.where(:id => topic.id).update_all("response_count = response_count - 1")
|
ForumTopic.where(:id => topic.id).update_all("response_count = response_count - 1")
|
||||||
topic.response_count -= 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
topic.response_count -= 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_is_deleted
|
def initialize_is_deleted
|
||||||
@@ -189,7 +189,7 @@ class ForumPost < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def forum_topic_page
|
def forum_topic_page
|
||||||
((ForumPost.where("topic_id = ? and created_at <= ?", topic_id, created_at).count) / Danbooru.config.posts_per_page.to_f).ceil
|
(ForumPost.where("topic_id = ? and created_at <= ?", topic_id, created_at).count / Danbooru.config.posts_per_page.to_f).ceil
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_original_post?(original_post_id = nil)
|
def is_original_post?(original_post_id = nil)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ForumTopic < ApplicationRecord
|
|||||||
MIN_LEVELS = {
|
MIN_LEVELS = {
|
||||||
None: 0,
|
None: 0,
|
||||||
Moderator: User::Levels::MODERATOR,
|
Moderator: User::Levels::MODERATOR,
|
||||||
Admin: User::Levels::ADMIN,
|
Admin: User::Levels::ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
belongs_to_creator
|
belongs_to_creator
|
||||||
@@ -105,10 +105,15 @@ class ForumTopic < ApplicationRecord
|
|||||||
ForumTopicVisit.create(:user_id => user.id, :forum_topic_id => id, :last_read_at => updated_at)
|
ForumTopicVisit.create(:user_id => user.id, :forum_topic_id => id, :last_read_at => updated_at)
|
||||||
end
|
end
|
||||||
|
|
||||||
has_unread_topics = ForumTopic.permitted.active.where("forum_topics.updated_at >= ?", user.last_forum_read_at)
|
has_unread_topics =
|
||||||
|
ForumTopic
|
||||||
|
.permitted
|
||||||
|
.active
|
||||||
|
.where("forum_topics.updated_at >= ?", user.last_forum_read_at)
|
||||||
.joins("left join forum_topic_visits on (forum_topic_visits.forum_topic_id = forum_topics.id and forum_topic_visits.user_id = #{user.id})")
|
.joins("left join forum_topic_visits on (forum_topic_visits.forum_topic_id = forum_topics.id and forum_topic_visits.user_id = #{user.id})")
|
||||||
.where("(forum_topic_visits.id is null or forum_topic_visits.last_read_at < forum_topics.updated_at)")
|
.where("(forum_topic_visits.id is null or forum_topic_visits.last_read_at < forum_topics.updated_at)")
|
||||||
.exists?
|
.exists?
|
||||||
|
|
||||||
unless has_unread_topics
|
unless has_unread_topics
|
||||||
user.update_attribute(:last_forum_read_at, Time.now)
|
user.update_attribute(:last_forum_read_at, Time.now)
|
||||||
ForumTopicVisit.prune!(user)
|
ForumTopicVisit.prune!(user)
|
||||||
@@ -170,8 +175,6 @@ class ForumTopic < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_orignal_post
|
def update_orignal_post
|
||||||
if original_post
|
original_post&.update_columns(:updater_id => CurrentUser.id, :updated_at => Time.now)
|
||||||
original_post.update_columns(:updater_id => CurrentUser.id, :updated_at => Time.now)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class IpAddress < ApplicationRecord
|
|||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
# include the subnet mask only when the IP denotes a subnet.
|
# include the subnet mask only when the IP denotes a subnet.
|
||||||
ip_addr.size > 1 ? ip_addr.to_string : ip_addr.to_s
|
(ip_addr.size > 1) ? ip_addr.to_string : ip_addr.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def readonly?
|
def readonly?
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class PixivUgoiraFrameData < ApplicationRecord
|
|||||||
|
|
||||||
if data[0]["delay_msec"]
|
if data[0]["delay_msec"]
|
||||||
self.data = data.map.with_index do |datum, i|
|
self.data = data.map.with_index do |datum, i|
|
||||||
filename = "%06d.jpg" % [i]
|
filename = format("%06d.jpg", i)
|
||||||
{"delay" => datum["delay_msec"], "file" => filename}
|
{"delay" => datum["delay_msec"], "file" => filename}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
class PoolArchive < ApplicationRecord
|
class PoolArchive < ApplicationRecord
|
||||||
|
|
||||||
belongs_to :updater, :class_name => "User"
|
belongs_to :updater, :class_name => "User"
|
||||||
|
|
||||||
def self.enabled?
|
def self.enabled?
|
||||||
|
|||||||
@@ -222,9 +222,7 @@ class Post < ApplicationRecord
|
|||||||
is_image? && image_width.present? && image_width > Danbooru.config.large_image_width
|
is_image? && image_width.present? && image_width > Danbooru.config.large_image_width
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_large
|
alias has_large has_large?
|
||||||
!!has_large?
|
|
||||||
end
|
|
||||||
|
|
||||||
def large_image_width
|
def large_image_width
|
||||||
if has_large?
|
if has_large?
|
||||||
@@ -481,7 +479,7 @@ class Post < ApplicationRecord
|
|||||||
url = URI.extract(str, ['http', 'https'])
|
url = URI.extract(str, ['http', 'https'])
|
||||||
if url.any?
|
if url.any?
|
||||||
url = url[0]
|
url = url[0]
|
||||||
if (url =~ /^https?:\/\/twitpic.com\/show\/large\/[a-z0-9]+/i)
|
if url =~ /^https?:\/\/twitpic.com\/show\/large\/[a-z0-9]+/i
|
||||||
url.gsub!(/show\/large\//, "")
|
url.gsub!(/show\/large\//, "")
|
||||||
index = url.rindex('.')
|
index = url.rindex('.')
|
||||||
url = url[0..index - 1]
|
url = url[0..index - 1]
|
||||||
@@ -524,7 +522,7 @@ class Post < ApplicationRecord
|
|||||||
|
|
||||||
url = Addressable::URI.parse(normalized_source)
|
url = Addressable::URI.parse(normalized_source)
|
||||||
url.domain
|
url.domain
|
||||||
rescue
|
rescue StandardError
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -558,7 +556,7 @@ class Post < ApplicationRecord
|
|||||||
decrement_tags = tag_array_was - tag_array
|
decrement_tags = tag_array_was - tag_array
|
||||||
|
|
||||||
decrement_tags_except_requests = decrement_tags.reject {|tag| tag == "tagme" || tag.end_with?("_request")}
|
decrement_tags_except_requests = decrement_tags.reject {|tag| tag == "tagme" || tag.end_with?("_request")}
|
||||||
if decrement_tags_except_requests.size > 0 && !CurrentUser.is_builder? && CurrentUser.created_at > 1.week.ago
|
if !decrement_tags_except_requests.empty? && !CurrentUser.is_builder? && CurrentUser.created_at > 1.week.ago
|
||||||
self.errors.add(:updater_id, "must have an account at least 1 week old to remove tags")
|
self.errors.add(:updater_id, "must have an account at least 1 week old to remove tags")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -596,8 +594,8 @@ class Post < ApplicationRecord
|
|||||||
if old_tag_string
|
if old_tag_string
|
||||||
# If someone else committed changes to this post before we did,
|
# If someone else committed changes to this post before we did,
|
||||||
# then try to merge the tag changes together.
|
# then try to merge the tag changes together.
|
||||||
current_tags = tag_array_was()
|
current_tags = tag_array_was
|
||||||
new_tags = tag_array()
|
new_tags = tag_array
|
||||||
old_tags = Tag.scan_tags(old_tag_string)
|
old_tags = Tag.scan_tags(old_tag_string)
|
||||||
|
|
||||||
kept_tags = current_tags & new_tags
|
kept_tags = current_tags & new_tags
|
||||||
@@ -645,7 +643,7 @@ class Post < ApplicationRecord
|
|||||||
normalized_tags = add_automatic_tags(normalized_tags)
|
normalized_tags = add_automatic_tags(normalized_tags)
|
||||||
normalized_tags = remove_invalid_tags(normalized_tags)
|
normalized_tags = remove_invalid_tags(normalized_tags)
|
||||||
normalized_tags = Tag.convert_cosplay_tags(normalized_tags)
|
normalized_tags = Tag.convert_cosplay_tags(normalized_tags)
|
||||||
normalized_tags = normalized_tags + Tag.create_for_list(TagImplication.automatic_tags_for(normalized_tags))
|
normalized_tags += Tag.create_for_list(TagImplication.automatic_tags_for(normalized_tags))
|
||||||
normalized_tags = TagImplication.with_descendants(normalized_tags)
|
normalized_tags = TagImplication.with_descendants(normalized_tags)
|
||||||
normalized_tags = normalized_tags.compact.uniq.sort
|
normalized_tags = normalized_tags.compact.uniq.sort
|
||||||
normalized_tags = Tag.create_for_list(normalized_tags)
|
normalized_tags = Tag.create_for_list(normalized_tags)
|
||||||
@@ -734,7 +732,7 @@ class Post < ApplicationRecord
|
|||||||
casesensitive_metatags, tags = tags.partition {|x| x =~ /\A(?:source):/i}
|
casesensitive_metatags, tags = tags.partition {|x| x =~ /\A(?:source):/i}
|
||||||
# Reuse the following metatags after the post has been saved
|
# Reuse the following metatags after the post has been saved
|
||||||
casesensitive_metatags += tags.select {|x| x =~ /\A(?:newpool):/i}
|
casesensitive_metatags += tags.select {|x| x =~ /\A(?:newpool):/i}
|
||||||
if casesensitive_metatags.length > 0
|
if !casesensitive_metatags.empty?
|
||||||
case casesensitive_metatags[-1]
|
case casesensitive_metatags[-1]
|
||||||
when /^source:none$/i
|
when /^source:none$/i
|
||||||
self.source = ""
|
self.source = ""
|
||||||
@@ -825,19 +823,19 @@ class Post < ApplicationRecord
|
|||||||
|
|
||||||
when /^-favgroup:(\d+)$/i
|
when /^-favgroup:(\d+)$/i
|
||||||
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
||||||
favgroup.remove!(id) if favgroup
|
favgroup&.remove!(id)
|
||||||
|
|
||||||
when /^-favgroup:(.+)$/i
|
when /^-favgroup:(.+)$/i
|
||||||
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
||||||
favgroup.remove!(id) if favgroup
|
favgroup&.remove!(id)
|
||||||
|
|
||||||
when /^favgroup:(\d+)$/i
|
when /^favgroup:(\d+)$/i
|
||||||
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
||||||
favgroup.add!(id) if favgroup
|
favgroup&.add!(id)
|
||||||
|
|
||||||
when /^favgroup:(.+)$/i
|
when /^favgroup:(.+)$/i
|
||||||
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
||||||
favgroup.add!(id) if favgroup
|
favgroup&.add!(id)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -879,7 +877,7 @@ class Post < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def has_tag?(tag)
|
def has_tag?(tag)
|
||||||
!!(tag_string =~ /(?:^| )(?:#{tag})(?:$| )/)
|
tag_string.match?(/(?:^| )(?:#{tag})(?:$| )/)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_tag(tag)
|
def add_tag(tag)
|
||||||
@@ -910,7 +908,6 @@ class Post < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module FavoriteMethods
|
module FavoriteMethods
|
||||||
def clean_fav_string?
|
def clean_fav_string?
|
||||||
true
|
true
|
||||||
@@ -925,10 +922,10 @@ class Post < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def favorited_by?(user_id = CurrentUser.id)
|
def favorited_by?(user_id = CurrentUser.id)
|
||||||
!!(fav_string =~ /(?:\A| )fav:#{user_id}(?:\Z| )/)
|
fav_string.match?(/(?:\A| )fav:#{user_id}(?:\Z| )/)
|
||||||
end
|
end
|
||||||
|
|
||||||
alias_method :is_favorited?, :favorited_by?
|
alias is_favorited? favorited_by?
|
||||||
|
|
||||||
def append_user_to_fav_string(user_id)
|
def append_user_to_fav_string(user_id)
|
||||||
update_column(:fav_string, (fav_string + " fav:#{user_id}").strip)
|
update_column(:fav_string, (fav_string + " fav:#{user_id}").strip)
|
||||||
@@ -972,7 +969,7 @@ class Post < ApplicationRecord
|
|||||||
|
|
||||||
if active_id.present?
|
if active_id.present?
|
||||||
active_group = FavoriteGroup.where(:id => active_id.to_i).first
|
active_group = FavoriteGroup.where(:id => active_id.to_i).first
|
||||||
groups << active_group if active_group && active_group.contains?(self.id)
|
groups << active_group if active_group&.contains?(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
groups += CurrentUser.user.favorite_groups.select do |favgroup|
|
groups += CurrentUser.user.favorite_groups.select do |favgroup|
|
||||||
@@ -1016,7 +1013,7 @@ class Post < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def has_active_pools?
|
def has_active_pools?
|
||||||
pools.undeleted.length > 0
|
!pools.undeleted.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def belongs_to_pool?(pool)
|
def belongs_to_pool?(pool)
|
||||||
@@ -1091,7 +1088,7 @@ class Post < ApplicationRecord
|
|||||||
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && !Tag.has_metatag?(tags, "status", "-status")
|
tags += " -status:deleted" if CurrentUser.hide_deleted_posts? && !Tag.has_metatag?(tags, "status", "-status")
|
||||||
tags = Tag.normalize_query(tags)
|
tags = Tag.normalize_query(tags)
|
||||||
|
|
||||||
# optimize some cases. these are just estimates but at these
|
# Optimize some cases. these are just estimates but at these
|
||||||
# quantities being off by a few hundred doesn't matter much
|
# quantities being off by a few hundred doesn't matter much
|
||||||
if Danbooru.config.estimate_post_counts
|
if Danbooru.config.estimate_post_counts
|
||||||
if tags == ""
|
if tags == ""
|
||||||
@@ -1207,7 +1204,7 @@ class Post < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_parent_on_destroy
|
def update_parent_on_destroy
|
||||||
parent.update_has_children_flag if parent
|
parent&.update_has_children_flag
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_children_on_destroy
|
def update_children_on_destroy
|
||||||
@@ -1713,18 +1710,18 @@ class Post < ApplicationRecord
|
|||||||
if new_general_tags.present?
|
if new_general_tags.present?
|
||||||
n = new_general_tags.size
|
n = new_general_tags.size
|
||||||
tag_wiki_links = new_general_tags.map { |tag| "[[#{tag.name}]]" }
|
tag_wiki_links = new_general_tags.map { |tag| "[[#{tag.name}]]" }
|
||||||
self.warnings[:base] << "Created #{n} new #{n == 1 ? "tag" : "tags"}: #{tag_wiki_links.join(", ")}"
|
self.warnings[:base] << "Created #{n} new #{(n == 1) ? "tag" : "tags"}: #{tag_wiki_links.join(", ")}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if repopulated_tags.present?
|
if repopulated_tags.present?
|
||||||
n = repopulated_tags.size
|
n = repopulated_tags.size
|
||||||
tag_wiki_links = repopulated_tags.map { |tag| "[[#{tag.name}]]" }
|
tag_wiki_links = repopulated_tags.map { |tag| "[[#{tag.name}]]" }
|
||||||
self.warnings[:base] << "Repopulated #{n} old #{n == 1 ? "tag" : "tags"}: #{tag_wiki_links.join(", ")}"
|
self.warnings[:base] << "Repopulated #{n} old #{(n == 1) ? "tag" : "tags"}: #{tag_wiki_links.join(", ")}"
|
||||||
end
|
end
|
||||||
|
|
||||||
new_artist_tags.each do |tag|
|
new_artist_tags.each do |tag|
|
||||||
if tag.artist.blank?
|
if tag.artist.blank?
|
||||||
self.warnings[:base] << "Artist [[#{tag.name}]] requires an artist entry. \"Create new artist entry\":[/artists/new?artist%5Bname%5D=#{CGI::escape(tag.name)}]"
|
self.warnings[:base] << "Artist [[#{tag.name}]] requires an artist entry. \"Create new artist entry\":[/artists/new?artist%5Bname%5D=#{CGI.escape(tag.name)}]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1746,7 +1743,7 @@ class Post < ApplicationRecord
|
|||||||
return if tags.any? { |t| t.category == Tag.categories.artist }
|
return if tags.any? { |t| t.category == Tag.categories.artist }
|
||||||
return if Sources::Strategies.find(source).is_a?(Sources::Strategies::Null)
|
return if Sources::Strategies.find(source).is_a?(Sources::Strategies::Null)
|
||||||
|
|
||||||
self.warnings[:base] << "Artist tag is required. \"Create new artist tag\":[/artists/new?artist%5Bsource%5D=#{CGI::escape(source)}]. Ask on the forum if you need naming help"
|
self.warnings[:base] << "Artist tag is required. \"Create new artist tag\":[/artists/new?artist%5Bsource%5D=#{CGI.escape(source)}]. Ask on the forum if you need naming help"
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_copyright_tag
|
def has_copyright_tag
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class PostArchive < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def visible?
|
def visible?
|
||||||
post && post.visible?
|
post&.visible?
|
||||||
end
|
end
|
||||||
|
|
||||||
def diff(version = nil)
|
def diff(version = nil)
|
||||||
@@ -135,7 +135,7 @@ class PostArchive < ApplicationRecord
|
|||||||
:removed_tags => removed_tags,
|
:removed_tags => removed_tags,
|
||||||
:obsolete_added_tags => added_tags - latest_tags,
|
:obsolete_added_tags => added_tags - latest_tags,
|
||||||
:obsolete_removed_tags => removed_tags & latest_tags,
|
:obsolete_removed_tags => removed_tags & latest_tags,
|
||||||
:unchanged_tags => new_tags & old_tags,
|
:unchanged_tags => new_tags & old_tags
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class PostEvent
|
|||||||
"created_at": nil,
|
"created_at": nil,
|
||||||
"reason": nil,
|
"reason": nil,
|
||||||
"is_resolved": nil,
|
"is_resolved": nil,
|
||||||
"type": nil,
|
"type": nil
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -33,5 +33,4 @@ class PostReplacement < ApplicationRecord
|
|||||||
tags = tags.map { |tag| "-#{tag}" }
|
tags = tags.map { |tag| "-#{tag}" }
|
||||||
tags.join(" ")
|
tags.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class PostVersion < ApplicationRecord
|
|||||||
:removed_tags => removed_tags,
|
:removed_tags => removed_tags,
|
||||||
:obsolete_added_tags => added_tags - latest_tags,
|
:obsolete_added_tags => added_tags - latest_tags,
|
||||||
:obsolete_removed_tags => removed_tags & latest_tags,
|
:obsolete_removed_tags => removed_tags & latest_tags,
|
||||||
:unchanged_tags => new_tags & old_tags,
|
:unchanged_tags => new_tags & old_tags
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ class SavedSearch < ApplicationRecord
|
|||||||
concerning :Labels do
|
concerning :Labels do
|
||||||
class_methods do
|
class_methods do
|
||||||
def normalize_label(label)
|
def normalize_label(label)
|
||||||
label.
|
label
|
||||||
to_s.
|
.to_s
|
||||||
strip.
|
.strip
|
||||||
downcase.
|
.downcase
|
||||||
gsub(/[[:space:]]/, "_")
|
.gsub(/[[:space:]]/, "_")
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_labels(user_id, params)
|
def search_labels(user_id, params)
|
||||||
@@ -67,17 +67,15 @@ class SavedSearch < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def labels_for(user_id)
|
def labels_for(user_id)
|
||||||
SavedSearch.
|
SavedSearch
|
||||||
where(user_id: user_id).
|
.where(user_id: user_id)
|
||||||
order("label").
|
.order("label")
|
||||||
pluck(Arel.sql("distinct unnest(labels) as label"))
|
.pluck(Arel.sql("distinct unnest(labels) as label"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_labels
|
def normalize_labels
|
||||||
self.labels = labels.
|
self.labels = labels.map {|x| SavedSearch.normalize_label(x)}.reject(&:blank?)
|
||||||
map {|x| SavedSearch.normalize_label(x)}.
|
|
||||||
reject {|x| x.blank?}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def label_string
|
def label_string
|
||||||
@@ -137,13 +135,13 @@ class SavedSearch < ApplicationRecord
|
|||||||
concerning :Queries do
|
concerning :Queries do
|
||||||
class_methods do
|
class_methods do
|
||||||
def queries_for(user_id, label: nil, options: {})
|
def queries_for(user_id, label: nil, options: {})
|
||||||
SavedSearch.
|
SavedSearch
|
||||||
where(user_id: user_id).
|
.where(user_id: user_id)
|
||||||
labeled(label).
|
.labeled(label)
|
||||||
pluck(:query).
|
.pluck(:query)
|
||||||
map {|x| Tag.normalize_query(x, sort: true)}.
|
.map {|x| Tag.normalize_query(x, sort: true)}
|
||||||
sort.
|
.sort
|
||||||
uniq
|
.uniq
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -156,7 +154,7 @@ class SavedSearch < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :disable_labels
|
attr_reader :disable_labels
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
validates :query, presence: true
|
validates :query, presence: true
|
||||||
validate :validate_count
|
validate :validate_count
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ class Tag < ApplicationRecord
|
|||||||
module CategoryMethods
|
module CategoryMethods
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
def categories
|
def categories
|
||||||
@category_mapping ||= CategoryMapping.new
|
@categories ||= CategoryMapping.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_category_for(tag_name)
|
def select_category_for(tag_name)
|
||||||
@@ -170,7 +170,7 @@ class Tag < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_category_post_counts
|
def update_category_post_counts
|
||||||
Post.with_timeout(30_000, nil, {:tags => name}) do
|
Post.with_timeout(30_000, nil, :tags => name) do
|
||||||
Post.raw_tag_match(name).where("true /* Tag#update_category_post_counts */").find_each do |post|
|
Post.raw_tag_match(name).where("true /* Tag#update_category_post_counts */").find_each do |post|
|
||||||
post.reload
|
post.reload
|
||||||
post.set_tag_counts(false)
|
post.set_tag_counts(false)
|
||||||
@@ -314,11 +314,7 @@ class Tag < ApplicationRecord
|
|||||||
object.to_f
|
object.to_f
|
||||||
|
|
||||||
when :date, :datetime
|
when :date, :datetime
|
||||||
begin
|
Time.zone.parse(object) rescue nil
|
||||||
Time.zone.parse(object)
|
|
||||||
rescue Exception
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
when :age
|
when :age
|
||||||
DurationParser.parse(object).ago
|
DurationParser.parse(object).ago
|
||||||
@@ -750,7 +746,7 @@ class Tag < ApplicationRecord
|
|||||||
when "order"
|
when "order"
|
||||||
g2 = g2.downcase
|
g2 = g2.downcase
|
||||||
|
|
||||||
order, suffix, _ = g2.partition(/_(asc|desc)\z/i)
|
order, suffix, _tail = g2.partition(/_(asc|desc)\z/i)
|
||||||
if order.in?(COUNT_METATAG_SYNONYMS)
|
if order.in?(COUNT_METATAG_SYNONYMS)
|
||||||
g2 = order.singularize + "_count" + suffix
|
g2 = order.singularize + "_count" + suffix
|
||||||
end
|
end
|
||||||
@@ -898,10 +894,14 @@ class Tag < ApplicationRecord
|
|||||||
name = normalize_name(name)
|
name = normalize_name(name)
|
||||||
wildcard_name = name + '*'
|
wildcard_name = name + '*'
|
||||||
|
|
||||||
query1 = Tag.select("tags.name, tags.post_count, tags.category, null AS antecedent_name")
|
query1 =
|
||||||
|
Tag
|
||||||
|
.select("tags.name, tags.post_count, tags.category, null AS antecedent_name")
|
||||||
.search(:name_matches => wildcard_name, :order => "count").limit(limit)
|
.search(:name_matches => wildcard_name, :order => "count").limit(limit)
|
||||||
|
|
||||||
query2 = TagAlias.select("tags.name, tags.post_count, tags.category, tag_aliases.antecedent_name")
|
query2 =
|
||||||
|
TagAlias
|
||||||
|
.select("tags.name, tags.post_count, tags.category, tag_aliases.antecedent_name")
|
||||||
.joins("INNER JOIN tags ON tags.name = tag_aliases.consequent_name")
|
.joins("INNER JOIN tags ON tags.name = tag_aliases.consequent_name")
|
||||||
.where("tag_aliases.antecedent_name LIKE ? ESCAPE E'\\\\'", wildcard_name.to_escaped_for_sql_like)
|
.where("tag_aliases.antecedent_name LIKE ? ESCAPE E'\\\\'", wildcard_name.to_escaped_for_sql_like)
|
||||||
.active
|
.active
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ class TagAlias < TagRelationship
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_mod_action
|
def create_mod_action
|
||||||
alias_desc = %Q("tag alias ##{id}":[#{Rails.application.routes.url_helpers.tag_alias_path(self)}]: [[#{antecedent_name}]] -> [[#{consequent_name}]])
|
alias_desc = %("tag alias ##{id}":[#{Rails.application.routes.url_helpers.tag_alias_path(self)}]: [[#{antecedent_name}]] -> [[#{consequent_name}]])
|
||||||
|
|
||||||
if saved_change_to_id?
|
if saved_change_to_id?
|
||||||
ModAction.log("created #{status} #{alias_desc}", :tag_alias_create)
|
ModAction.log("created #{status} #{alias_desc}", :tag_alias_create)
|
||||||
@@ -187,9 +187,9 @@ class TagAlias < TagRelationship
|
|||||||
change_desc = saved_changes.except(:updated_at).map do |attribute, values|
|
change_desc = saved_changes.except(:updated_at).map do |attribute, values|
|
||||||
old, new = values[0], values[1]
|
old, new = values[0], values[1]
|
||||||
if old.nil?
|
if old.nil?
|
||||||
%Q(set #{attribute} to "#{new}")
|
%(set #{attribute} to "#{new}")
|
||||||
else
|
else
|
||||||
%Q(changed #{attribute} from "#{old}" to "#{new}")
|
%(changed #{attribute} from "#{old}" to "#{new}")
|
||||||
end
|
end
|
||||||
end.join(", ")
|
end.join(", ")
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class TagImplication < TagRelationship
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_mod_action
|
def create_mod_action
|
||||||
implication = %Q("tag implication ##{id}":[#{Rails.application.routes.url_helpers.tag_implication_path(self)}]: [[#{antecedent_name}]] -> [[#{consequent_name}]])
|
implication = %("tag implication ##{id}":[#{Rails.application.routes.url_helpers.tag_implication_path(self)}]: [[#{antecedent_name}]] -> [[#{consequent_name}]])
|
||||||
|
|
||||||
if saved_change_to_id?
|
if saved_change_to_id?
|
||||||
ModAction.log("created #{status} #{implication}", :tag_implication_create)
|
ModAction.log("created #{status} #{implication}", :tag_implication_create)
|
||||||
@@ -179,9 +179,9 @@ class TagImplication < TagRelationship
|
|||||||
change_desc = saved_changes.except(:updated_at).map do |attribute, values|
|
change_desc = saved_changes.except(:updated_at).map do |attribute, values|
|
||||||
old, new = values[0], values[1]
|
old, new = values[0], values[1]
|
||||||
if old.nil?
|
if old.nil?
|
||||||
%Q(set #{attribute} to "#{new}")
|
%(set #{attribute} to "#{new}")
|
||||||
else
|
else
|
||||||
%Q(changed #{attribute} from "#{old}" to "#{new}")
|
%(changed #{attribute} from "#{old}" to "#{new}")
|
||||||
end
|
end
|
||||||
end.join(", ")
|
end.join(", ")
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ class Upload < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
attr_accessor :as_pending, :replaced_post, :file
|
attr_accessor :as_pending, :replaced_post, :file
|
||||||
belongs_to :uploader, :class_name => "User"
|
belongs_to :uploader, :class_name => "User"
|
||||||
belongs_to :post, optional: true
|
belongs_to :post, optional: true
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class User < ApplicationRecord
|
|||||||
:banned,
|
:banned,
|
||||||
:approver,
|
:approver,
|
||||||
:voter,
|
:voter,
|
||||||
:super_voter,
|
:super_voter
|
||||||
]
|
]
|
||||||
|
|
||||||
# candidates for removal:
|
# candidates for removal:
|
||||||
@@ -199,7 +199,7 @@ class User < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def reset_password_and_deliver_notice
|
def reset_password_and_deliver_notice
|
||||||
new_password = reset_password()
|
new_password = reset_password
|
||||||
Maintenance::User::PasswordResetMailer.confirmation(self, new_password).deliver_now
|
Maintenance::User::PasswordResetMailer.confirmation(self, new_password).deliver_now
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -570,23 +570,23 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
module ApiMethods
|
module ApiMethods
|
||||||
def api_attributes
|
def api_attributes
|
||||||
attributes = [
|
attributes = %i[
|
||||||
:id, :created_at, :name, :inviter_id, :level, :base_upload_limit,
|
id created_at name inviter_id level base_upload_limit
|
||||||
:post_upload_count, :post_update_count, :note_update_count, :is_banned,
|
post_upload_count post_update_count note_update_count is_banned
|
||||||
:can_approve_posts, :can_upload_free, :is_super_voter, :level_string,
|
can_approve_posts can_upload_free is_super_voter level_string
|
||||||
]
|
]
|
||||||
|
|
||||||
if id == CurrentUser.user.id
|
if id == CurrentUser.user.id
|
||||||
attributes += BOOLEAN_ATTRIBUTES
|
attributes += BOOLEAN_ATTRIBUTES
|
||||||
attributes += [
|
attributes += %i[
|
||||||
:updated_at, :email, :last_logged_in_at, :last_forum_read_at,
|
updated_at email last_logged_in_at last_forum_read_at
|
||||||
:comment_threshold, :default_image_size,
|
comment_threshold default_image_size
|
||||||
:favorite_tags, :blacklisted_tags, :time_zone, :per_page,
|
favorite_tags blacklisted_tags time_zone per_page
|
||||||
:custom_style, :favorite_count, :api_regen_multiplier,
|
custom_style favorite_count api_regen_multiplier
|
||||||
:api_burst_limit, :remaining_api_limit, :statement_timeout,
|
api_burst_limit remaining_api_limit statement_timeout
|
||||||
:favorite_group_limit, :favorite_limit, :tag_query_limit,
|
favorite_group_limit favorite_limit tag_query_limit
|
||||||
:can_comment_vote?, :can_remove_from_pools?, :is_comment_limited?,
|
can_comment_vote? can_remove_from_pools? is_comment_limited?
|
||||||
:can_comment?, :can_upload?, :max_saved_searches, :theme
|
can_comment? can_upload? max_saved_searches theme
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -595,13 +595,13 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
# extra attributes returned for /users/:id.json but not for /users.json.
|
# extra attributes returned for /users/:id.json but not for /users.json.
|
||||||
def full_attributes
|
def full_attributes
|
||||||
[
|
%i[
|
||||||
:wiki_page_version_count, :artist_version_count,
|
wiki_page_version_count artist_version_count
|
||||||
:artist_commentary_version_count, :pool_version_count,
|
artist_commentary_version_count pool_version_count
|
||||||
:forum_post_count, :comment_count, :favorite_group_count,
|
forum_post_count comment_count favorite_group_count
|
||||||
:appeal_count, :flag_count, :positive_feedback_count,
|
appeal_count flag_count positive_feedback_count
|
||||||
:neutral_feedback_count, :negative_feedback_count, :upload_limit,
|
neutral_feedback_count negative_feedback_count upload_limit
|
||||||
:max_upload_limit
|
max_upload_limit
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -743,13 +743,13 @@ class User < ApplicationRecord
|
|||||||
if bitprefs_include
|
if bitprefs_include
|
||||||
bitprefs_include.reverse!
|
bitprefs_include.reverse!
|
||||||
q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = :bits::bit(:len)",
|
q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = :bits::bit(:len)",
|
||||||
{:len => bitprefs_length, :bits => bitprefs_include})
|
:len => bitprefs_length, :bits => bitprefs_include)
|
||||||
end
|
end
|
||||||
|
|
||||||
if bitprefs_exclude
|
if bitprefs_exclude
|
||||||
bitprefs_exclude.reverse!
|
bitprefs_exclude.reverse!
|
||||||
q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = 0::bit(:len)",
|
q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = 0::bit(:len)",
|
||||||
{:len => bitprefs_length, :bits => bitprefs_exclude})
|
:len => bitprefs_length, :bits => bitprefs_exclude)
|
||||||
end
|
end
|
||||||
|
|
||||||
if params[:current_user_first].to_s.truthy? && !CurrentUser.is_anonymous?
|
if params[:current_user_first].to_s.truthy? && !CurrentUser.is_anonymous?
|
||||||
|
|||||||
@@ -128,13 +128,13 @@ class WikiPage < ApplicationRecord
|
|||||||
|
|
||||||
tag_was = Tag.find_by_name(Tag.normalize_name(title_was))
|
tag_was = Tag.find_by_name(Tag.normalize_name(title_was))
|
||||||
if tag_was.present? && tag_was.post_count > 0
|
if tag_was.present? && tag_was.post_count > 0
|
||||||
warnings[:base] << %Q!Warning: {{#{title_was}}} still has #{tag_was.post_count} #{"post".pluralize(tag_was.post_count)}. Be sure to move the posts!
|
warnings[:base] << %!Warning: {{#{title_was}}} still has #{tag_was.post_count} #{"post".pluralize(tag_was.post_count)}. Be sure to move the posts!
|
||||||
end
|
end
|
||||||
|
|
||||||
broken_wikis = WikiPage.linked_to(title_was)
|
broken_wikis = WikiPage.linked_to(title_was)
|
||||||
if broken_wikis.count > 0
|
if broken_wikis.count > 0
|
||||||
broken_wiki_search = Rails.application.routes.url_helpers.wiki_pages_path(search: { linked_to: title_was })
|
broken_wiki_search = Rails.application.routes.url_helpers.wiki_pages_path(search: { linked_to: title_was })
|
||||||
warnings[:base] << %Q!Warning: [[#{title_was}]] is still linked from "#{broken_wikis.count} #{"other wiki page".pluralize(broken_wikis.count)}":[#{broken_wiki_search}]. Update #{broken_wikis.count > 1 ? "these wikis" : "this wiki"} to link to [[#{title}]] instead!
|
warnings[:base] << %!Warning: [[#{title_was}]] is still linked from "#{broken_wikis.count} #{"other wiki page".pluralize(broken_wikis.count)}":[#{broken_wiki_search}]. Update #{(broken_wikis.count > 1) ? "these wikis" : "this wiki"} to link to [[#{title}]] instead!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class Presenter
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.u(s)
|
def self.u(s)
|
||||||
URI.escape(s)
|
CGI.escape(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
def h(s)
|
def h(s)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
=begin rdoc
|
# rdoc
|
||||||
A tag set represents a set of tags that are displayed together.
|
# A tag set represents a set of tags that are displayed together.
|
||||||
This class makes it easy to fetch the categories for all the
|
# This class makes it easy to fetch the categories for all the
|
||||||
tags in one call instead of fetching them sequentially.
|
# tags in one call instead of fetching them sequentially.
|
||||||
=end
|
|
||||||
|
|
||||||
class TagSetPresenter < Presenter
|
class TagSetPresenter < Presenter
|
||||||
extend Memoist
|
extend Memoist
|
||||||
@@ -77,7 +76,7 @@ class TagSetPresenter < Presenter
|
|||||||
artists = "drawn by #{artists}" if artists.present?
|
artists = "drawn by #{artists}" if artists.present?
|
||||||
|
|
||||||
strings = "#{characters} #{copyrights} #{artists}"
|
strings = "#{characters} #{copyrights} #{artists}"
|
||||||
strings.blank? ? default : strings
|
strings.presence || default
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -133,7 +132,7 @@ class TagSetPresenter < Presenter
|
|||||||
if count >= 10_000
|
if count >= 10_000
|
||||||
post_count = "#{count / 1_000}k"
|
post_count = "#{count / 1_000}k"
|
||||||
elsif count >= 1_000
|
elsif count >= 1_000
|
||||||
post_count = "%.1fk" % (count / 1_000.0)
|
post_count = format("%.1fk", (count / 1_000.0))
|
||||||
else
|
else
|
||||||
post_count = count
|
post_count = count
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ class UserPresenter
|
|||||||
slots_tooltip = "Next free slot: #{template.time_ago_in_words(user.next_free_upload_slot)}"
|
slots_tooltip = "Next free slot: #{template.time_ago_in_words(user.next_free_upload_slot)}"
|
||||||
limit_tooltip = <<-EOS.strip_heredoc
|
limit_tooltip = <<-EOS.strip_heredoc
|
||||||
Base: #{user.base_upload_limit}
|
Base: #{user.base_upload_limit}
|
||||||
Del. Rate: #{"%.2f" % user.adjusted_deletion_confidence}
|
Del. Rate: #{format("%.2f", user.adjusted_deletion_confidence)}
|
||||||
Multiplier: (1 - (#{"%.2f" % user.adjusted_deletion_confidence} / 15)) = #{user.upload_limit_multiplier}
|
Multiplier: (1 - (#{format("%.2f", user.adjusted_deletion_confidence)} / 15)) = #{user.upload_limit_multiplier}
|
||||||
Upload Limit: #{user.base_upload_limit} * #{"%.2f" % user.upload_limit_multiplier} = #{user.max_upload_limit}
|
Upload Limit: #{user.base_upload_limit} * #{format("%.2f", user.upload_limit_multiplier)} = #{user.max_upload_limit}
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
%{<abbr title="#{slots_tooltip}">#{user.used_upload_slots}</abbr> / <abbr title="#{limit_tooltip}">#{user.max_upload_limit}</abbr>}.html_safe
|
%{<abbr title="#{slots_tooltip}">#{user.used_upload_slots}</abbr> / <abbr title="#{limit_tooltip}">#{user.max_upload_limit}</abbr>}.html_safe
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class WikiPagePresenter
|
|||||||
|
|
||||||
escape_html = ->(str) {str.gsub(/&/, '&').gsub(/</, '<').gsub(/>/, '>')}
|
escape_html = ->(str) {str.gsub(/&/, '&').gsub(/</, '<').gsub(/>/, '>')}
|
||||||
|
|
||||||
output = thisarr;
|
output = thisarr
|
||||||
output.each { |q| q.replace(CGI.escape_html(q)) }
|
output.each { |q| q.replace(CGI.escape_html(q)) }
|
||||||
|
|
||||||
diffs.reverse_each do |hunk|
|
diffs.reverse_each do |hunk|
|
||||||
@@ -42,7 +42,7 @@ class WikiPagePresenter
|
|||||||
if chg.new_element.match(/^\r?\n$/)
|
if chg.new_element.match(/^\r?\n$/)
|
||||||
output.insert(chg.old_position, "[nl]")
|
output.insert(chg.old_position, "[nl]")
|
||||||
else
|
else
|
||||||
output.insert(chg.old_position, "#{escape_html[chg.new_element]}")
|
output.insert(chg.old_position, (escape_html[chg.new_element]).to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user