Merge pull request #3353 from BrokenEagle/feat-add-meta-tag-category

Migrated tag logic into config file and added fifth tag category meta
This commit is contained in:
Albert Yi
2017-11-13 11:44:15 -08:00
committed by GitHub
22 changed files with 384 additions and 359 deletions

View File

@@ -9,6 +9,7 @@
Danbooru.Autocomplete.initialize_all = function() { Danbooru.Autocomplete.initialize_all = function() {
if (Danbooru.meta("enable-auto-complete") === "true") { if (Danbooru.meta("enable-auto-complete") === "true") {
Danbooru.Autocomplete.enable_local_storage = this.test_local_storage(); Danbooru.Autocomplete.enable_local_storage = this.test_local_storage();
this.update_static_metatags();
this.initialize_tag_autocomplete(); this.initialize_tag_autocomplete();
this.initialize_mention_autocomplete(); this.initialize_mention_autocomplete();
this.prune_local_storage(); this.prune_local_storage();
@@ -94,7 +95,7 @@
var $fields_multiple = $('[data-autocomplete="tag-query"], [data-autocomplete="tag-edit"]'); var $fields_multiple = $('[data-autocomplete="tag-query"], [data-autocomplete="tag-edit"]');
var $fields_single = $('[data-autocomplete="tag"]'); var $fields_single = $('[data-autocomplete="tag"]');
var prefixes = "-|~|general:|gen:|artist:|art:|copyright:|copy:|co:|character:|char:|ch:"; var prefixes = "-|~|" + $.map(JSON.parse(Danbooru.meta("tag-category-names")), function (category) { return category + ':'}).join('|');
var metatags = "order|-status|status|-rating|rating|-locked|locked|child|filetype|-filetype|" + var metatags = "order|-status|status|-rating|rating|-locked|locked|child|filetype|-filetype|" +
"-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-fav|fav|ordfav|" + "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-fav|fav|ordfav|" +
"-pool|pool|ordpool|favgroup|-search|search"; "-pool|pool|ordpool|favgroup|-search|search";
@@ -326,10 +327,6 @@
"portrait", "landscape", "portrait", "landscape",
"filesize", "filesize_asc", "filesize", "filesize_asc",
"tagcount", "tagcount_asc", "tagcount", "tagcount_asc",
"gentags", "gentags_asc",
"arttags", "arttags_asc",
"chartags", "chartags_asc",
"copytags", "copytags_asc",
"rank", "rank",
"random" "random"
], ],
@@ -350,6 +347,11 @@
], ],
} }
//This must be done as a separate function as Danbooru.meta does not exist at program initialization
Danbooru.Autocomplete.update_static_metatags = function () {
Array.prototype.push.apply(Danbooru.Autocomplete.static_metatags.order,$.map(JSON.parse(Danbooru.meta("short-tag-category-names")), function(shorttag) { return [shorttag + "tags", shorttag + "tags_asc"]}));
}
Danbooru.Autocomplete.static_metatag_source = function(term, resp, metatag) { Danbooru.Autocomplete.static_metatag_source = function(term, resp, metatag) {
var sub_metatags = this.static_metatags[metatag]; var sub_metatags = this.static_metatags[metatag];

View File

@@ -2,7 +2,7 @@
Danbooru.RelatedTag = {}; Danbooru.RelatedTag = {};
Danbooru.RelatedTag.initialize_all = function() { Danbooru.RelatedTag.initialize_all = function() {
if ($("#c-posts").length || $("#c-uploads").length) { if ($("#c-posts #a-show").length || $("#c-uploads #a-new").length) {
this.initialize_buttons(); this.initialize_buttons();
$("#related-tags-container").hide(); $("#related-tags-container").hide();
$("#artist-tags-container").hide(); $("#artist-tags-container").hide();
@@ -12,10 +12,9 @@
Danbooru.RelatedTag.initialize_buttons = function() { Danbooru.RelatedTag.initialize_buttons = function() {
this.common_bind("#related-tags-button", ""); this.common_bind("#related-tags-button", "");
this.common_bind("#related-general-button", "general"); $.each(JSON.parse(Danbooru.meta("related-tag-button-list")), function(i,category) {
this.common_bind("#related-artists-button", "artist"); Danbooru.RelatedTag.common_bind("#related-" + category + "-button", category);
this.common_bind("#related-characters-button", "character"); });
this.common_bind("#related-copyrights-button", "copyright");
$("#find-artist-button").click(Danbooru.RelatedTag.find_artist); $("#find-artist-button").click(Danbooru.RelatedTag.find_artist);
} }

View File

@@ -211,6 +211,14 @@ body[data-user-can-approve-posts="true"] .post-preview {
} }
} }
.category-5 a, a.tag-type-5, .ui-state-focus a.tag-type-5 {
color: #F80;
&:hover {
color: #FA6;
}
}
.category-banned a, a.tag-type-banned,, .ui-state-focus a.tag-type-banned { .category-banned a, a.tag-type-banned,, .ui-state-focus a.tag-type-banned {
color: black; color: black;
background-color: red; background-color: red;

View File

@@ -118,10 +118,9 @@ class PostQueryBuilder
relation = add_range_relation(q[:filesize], "posts.file_size", relation) relation = add_range_relation(q[:filesize], "posts.file_size", relation)
relation = add_range_relation(q[:date], "posts.created_at", relation) relation = add_range_relation(q[:date], "posts.created_at", relation)
relation = add_range_relation(q[:age], "posts.created_at", relation) relation = add_range_relation(q[:age], "posts.created_at", relation)
relation = add_range_relation(q[:general_tag_count], "posts.tag_count_general", relation) TagCategory.categories.each do |category|
relation = add_range_relation(q[:artist_tag_count], "posts.tag_count_artist", relation) relation = add_range_relation(q["#{category}_tag_count".to_sym], "posts.tag_count_#{category}", relation)
relation = add_range_relation(q[:copyright_tag_count], "posts.tag_count_copyright", relation) end
relation = add_range_relation(q[:character_tag_count], "posts.tag_count_character", relation)
relation = add_range_relation(q[:post_tag_count], "posts.tag_count", relation) relation = add_range_relation(q[:post_tag_count], "posts.tag_count", relation)
relation = add_range_relation(q[:pixiv_id], "posts.pixiv_id", relation) relation = add_range_relation(q[:pixiv_id], "posts.pixiv_id", relation)
@@ -513,29 +512,11 @@ class PostQueryBuilder
when "tagcount_asc" when "tagcount_asc"
relation = relation.order("posts.tag_count ASC") relation = relation.order("posts.tag_count ASC")
when "gentags", "gentags_desc" when /(#{TagCategory.short_name_regex})tags(?:\Z|_desc)/
relation = relation.order("posts.tag_count_general DESC") relation = relation.order("posts.tag_count_#{TagCategory.short_name_mapping[$1]} DESC")
when "gentags_asc" when /(#{TagCategory.short_name_regex})tags_asc/
relation = relation.order("posts.tag_count_general ASC") relation = relation.order("posts.tag_count_#{TagCategory.short_name_mapping[$1]} ASC")
when "arttags", "arttags_desc"
relation = relation.order("posts.tag_count_artist DESC")
when "arttags_asc"
relation = relation.order("posts.tag_count_artist ASC")
when "chartags", "chartags_desc"
relation = relation.order("posts.tag_count_character DESC")
when "chartags_asc"
relation = relation.order("posts.tag_count_character ASC")
when "copytags", "copytags_desc"
relation = relation.order("posts.tag_count_copyright DESC")
when "copytags_asc"
relation = relation.order("posts.tag_count_copyright ASC")
when "rank" when "rank"
relation = relation.order("log(3, posts.score) + (extract(epoch from posts.created_at) - extract(epoch from timestamp '2005-05-24')) / 35000 DESC") relation = relation.order("log(3, posts.score) + (extract(epoch from posts.created_at) - extract(epoch from timestamp '2005-05-24')) / 35000 DESC")

View File

@@ -0,0 +1,78 @@
class TagCategory
module Mappings
# Returns a hash mapping various tag categories to a numerical value.
def mapping
@@mapping ||= Hash[
Danbooru.config.full_tag_config_info.map {|k,v| v["extra"].map {|y| [y,v["category"]]}}
.reduce([],:+)]
.update(Hash[Danbooru.config.full_tag_config_info.map {|k,v| [v["short"],v["category"]]}])
.update( Hash[Danbooru.config.full_tag_config_info.map {|k,v| [k,v["category"]]}])
end
# Returns a hash mapping more suited for views
def canonical_mapping
@@canonical_mapping ||= Hash[Danbooru.config.full_tag_config_info.map {|k,v| [k.capitalize,v["category"]]}]
end
# Returns a hash mapping numerical category values to their string equivalent.
def reverse_mapping
@@reverse_mapping ||= Hash[Danbooru.config.full_tag_config_info.map {|k,v| [v["category"],k]}]
end
# Returns a hash mapping for the short name usage in metatags
def short_name_mapping
@@short_name_mapping ||= Hash[Danbooru.config.full_tag_config_info.map {|k,v| [v["short"],k]}]
end
# Returns a hash mapping for humanized_essential_tag_string (models/post.rb)
def humanized_mapping
@@humanized_mapping ||= Hash[Danbooru.config.full_tag_config_info.map {|k,v| [k,v["humanized"]]}]
end
# Returns a hash mapping for humanized_essential_tag_string (models/post.rb)
def header_mapping
@@header_mapping ||= Hash[Danbooru.config.full_tag_config_info.map {|k,v| [k,v["header"]]}]
end
# Returns a hash mapping for related tag buttons (javascripts/related_tag.js)
def related_button_mapping
@@related_button_mapping ||= Hash[Danbooru.config.full_tag_config_info.map {|k,v| [k,v["relatedbutton"]]}]
end
end
module Lists
def categories
@@categories ||= Danbooru.config.full_tag_config_info.keys
end
def short_name_list
@@short_name_list ||= short_name_mapping.keys
end
def humanized_list
Danbooru.config.humanized_tag_category_list
end
def split_header_list
Danbooru.config.split_tag_header_list
end
def categorized_list
Danbooru.config.categorized_tag_list
end
def related_button_list
Danbooru.config.related_tag_button_list
end
end
module Regexes
def short_name_regex
@@short_name_regex ||= short_name_list.join("|")
end
end
extend Mappings
extend Lists
extend Regexes
end

View File

@@ -616,30 +616,21 @@ class Post < ApplicationRecord
Post.expire_cache_for_all([""]) if new_record? || id <= 100_000 Post.expire_cache_for_all([""]) if new_record? || id <= 100_000
end end
def set_tag_count(category,tagcount)
self.send("tag_count_#{category}=",tagcount)
end
def inc_tag_count(category)
set_tag_count(category,self.send("tag_count_#{category}") + 1)
end
def set_tag_counts def set_tag_counts
self.tag_count = 0 self.tag_count = 0
self.tag_count_general = 0 TagCategory.categories {|x| set_tag_count(x,0)}
self.tag_count_artist = 0
self.tag_count_copyright = 0
self.tag_count_character = 0
categories = Tag.categories_for(tag_array, :disable_caching => true) categories = Tag.categories_for(tag_array, :disable_caching => true)
categories.each_value do |category| categories.each_value do |category|
self.tag_count += 1 self.tag_count += 1
inc_tag_count(TagCategory.reverse_mapping[category])
case category
when Tag.categories.general
self.tag_count_general += 1
when Tag.categories.artist
self.tag_count_artist += 1
when Tag.categories.copyright
self.tag_count_copyright += 1
when Tag.categories.character
self.tag_count_character += 1
end
end end
end end
@@ -918,31 +909,11 @@ class Post < ApplicationRecord
@tag_categories ||= Tag.categories_for(tag_array) @tag_categories ||= Tag.categories_for(tag_array)
end end
def copyright_tags
typed_tags("copyright")
end
def character_tags
typed_tags("character")
end
def artist_tags
typed_tags("artist")
end
def artist_tags_excluding_hidden
artist_tags - %w(banned_artist)
end
def general_tags
typed_tags("general")
end
def typed_tags(name) def typed_tags(name)
@typed_tags ||= {} @typed_tags ||= {}
@typed_tags[name] ||= begin @typed_tags[name] ||= begin
tag_array.select do |tag| tag_array.select do |tag|
tag_categories[tag] == Danbooru.config.tag_category_mapping[name] tag_categories[tag] == TagCategory.mapping[name]
end end
end end
end end
@@ -955,52 +926,36 @@ class Post < ApplicationRecord
@humanized_essential_tag_string ||= Cache.get("hets-#{id}", 1.hour.to_i) do @humanized_essential_tag_string ||= Cache.get("hets-#{id}", 1.hour.to_i) do
string = [] string = []
if character_tags.any? TagCategory.humanized_list.each do |category|
chartags = character_tags.slice(0, 5) typetags = typed_tags(category) - TagCategory.humanized_mapping[category]["exclusion"]
if character_tags.length > 5 if TagCategory.humanized_mapping[category]["slice"] > 0
chartags << "others" typetags = typetags.slice(0,TagCategory.humanized_mapping[category]["slice"]) + (typetags.length > TagCategory.humanized_mapping[category]["slice"] ? ["others"] : [])
end end
chartags = chartags.map do |tag| if TagCategory.humanized_mapping[category]["regexmap"] != //
tag.match(/^(.+?)(?:_\(.+\))?$/)[1] typetags = typetags.map do |tag|
tag.match(TagCategory.humanized_mapping[category]["regexmap"])[1]
end
end end
string << chartags.to_sentence if typetags.any?
end if category != "copyright" || typed_tags("character").any?
string << TagCategory.humanized_mapping[category]["formatstr"] % typetags.to_sentence
if copyright_tags.any? else
copytags = copyright_tags.slice(0, 5) string << typetags.to_sentence
if copyright_tags.length > 5 end
copytags << "others"
end end
copytags = copytags.to_sentence
string << (character_tags.any? ? "(#{copytags})" : copytags)
end end
if artist_tags_excluding_hidden.any?
string << "drawn by"
string << artist_tags_excluding_hidden.to_sentence
end
string.empty? ? "##{id}" : string.join(" ").tr("_", " ") string.empty? ? "##{id}" : string.join(" ").tr("_", " ")
end end
end end
def tag_string_copyright TagCategory.categories.each do |category|
copyright_tags.join(" ") define_method("tag_string_#{category}") do
end typed_tags(category).join(" ")
end
def tag_string_character
character_tags.join(" ")
end
def tag_string_artist
artist_tags.join(" ")
end
def tag_string_general
general_tags.join(" ")
end end
end end
module FavoriteMethods module FavoriteMethods
def clean_fav_string? def clean_fav_string?
true true
@@ -1182,15 +1137,10 @@ class Post < ApplicationRecord
end end
module CountMethods module CountMethods
def fix_post_counts def fix_post_counts(post)
post.set_tag_counts post.set_tag_counts
post.update_columns( args = Hash[TagCategory.categories.map {|x| ["tag_count_#{x}",post.send("tag_count_#{x}")]}].update(:tag_count => post.tag_count)
:tag_count => post.tag_count, post.update_columns(args)
:tag_count_general => post.tag_count_general,
:tag_count_artist => post.tag_count_artist,
:tag_count_copyright => post.tag_count_copyright,
:tag_count_character => post.tag_count_character
)
end end
def get_count_from_cache(tags) def get_count_from_cache(tags)
@@ -1572,7 +1522,7 @@ class Post < ApplicationRecord
end end
def method_attributes def method_attributes
list = super + [:uploader_name, :has_large, :tag_string_artist, :tag_string_character, :tag_string_copyright, :tag_string_general, :has_visible_children, :children_ids] list = super + [:uploader_name, :has_large, :has_visible_children, :children_ids] + TagCategory.categories.map {|x| "tag_string_#{x}".to_sym}
if visible? if visible?
list += [:file_url, :large_file_url, :preview_file_url] list += [:file_url, :large_file_url, :preview_file_url]
end end

View File

@@ -1,6 +1,7 @@
class Tag < ApplicationRecord class Tag < ApplicationRecord
COSINE_SIMILARITY_RELATED_TAG_THRESHOLD = 1000 COSINE_SIMILARITY_RELATED_TAG_THRESHOLD = 1000
METATAGS = "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-pool|pool|ordpool|-favgroup|favgroup|-fav|fav|ordfav|md5|-rating|rating|-locked|locked|width|height|mpixels|ratio|score|favcount|filesize|source|-source|id|-id|date|age|order|limit|-status|status|tagcount|gentags|arttags|chartags|copytags|parent|-parent|child|pixiv_id|pixiv|search|upvote|downvote|filetype|-filetype|flagger|-flagger|appealer|-appealer" METATAGS = "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-pool|pool|ordpool|-favgroup|favgroup|-fav|fav|ordfav|md5|-rating|rating|-locked|locked|width|height|mpixels|ratio|score|favcount|filesize|source|-source|id|-id|date|age|order|limit|-status|status|tagcount|parent|-parent|child|pixiv_id|pixiv|search|upvote|downvote|filetype|-filetype|flagger|-flagger|appealer|-appealer|" +
TagCategory.short_name_list.map {|x| "#{x}tags"}.join("|")
SUBQUERY_METATAGS = "commenter|comm|noter|noteupdater|artcomm|flagger|-flagger|appealer|-appealer" SUBQUERY_METATAGS = "commenter|comm|noter|noteupdater|artcomm|flagger|-flagger|appealer|-appealer"
attr_accessible :category, :as => [:moderator, :gold, :platinum, :member, :anonymous, :default, :builder, :admin] attr_accessible :category, :as => [:moderator, :gold, :platinum, :member, :anonymous, :default, :builder, :admin]
attr_accessible :is_locked, :as => [:moderator, :admin] attr_accessible :is_locked, :as => [:moderator, :admin]
@@ -26,18 +27,18 @@ class Tag < ApplicationRecord
end end
class CategoryMapping class CategoryMapping
Danbooru.config.reverse_tag_category_mapping.each do |value, category| TagCategory.reverse_mapping.each do |value, category|
define_method(category.downcase) do define_method(category) do
value value
end end
end end
def regexp def regexp
@regexp ||= Regexp.compile(Danbooru.config.tag_category_mapping.keys.sort_by {|x| -x.size}.join("|")) @regexp ||= Regexp.compile(TagCategory.mapping.keys.sort_by {|x| -x.size}.join("|"))
end end
def value_for(string) def value_for(string)
Danbooru.config.tag_category_mapping[string.to_s.downcase] || 0 TagCategory.mapping[string.to_s.downcase] || 0
end end
end end
@@ -124,7 +125,7 @@ class Tag < ApplicationRecord
end end
def category_name def category_name
Danbooru.config.reverse_tag_category_mapping[category] TagCategory.reverse_mapping[category].capitalize
end end
def update_category_cache_for_all def update_category_cache_for_all
@@ -140,7 +141,8 @@ class Tag < ApplicationRecord
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 post.set_tag_counts
Post.where(:id => post.id).update_all(:tag_count => post.tag_count, :tag_count_general => post.tag_count_general, :tag_count_artist => post.tag_count_artist, :tag_count_copyright => post.tag_count_copyright, :tag_count_character => post.tag_count_character) args = Hash[TagCategory.categories {|x| ["tag_count_#{x}",post.send("tag_count_#{x}")]}].update(:tag_count => post.tag_count)
Post.where(:id => post.id).update_all(args)
end end
end end
end end
@@ -175,7 +177,7 @@ class Tag < ApplicationRecord
counts = counts.to_a.select {|x| x[1] > trending_count_limit} counts = counts.to_a.select {|x| x[1] > trending_count_limit}
counts = counts.map do |tag_name, recent_count| counts = counts.map do |tag_name, recent_count|
tag = Tag.find_or_create_by_name(tag_name) tag = Tag.find_or_create_by_name(tag_name)
if tag.category == Danbooru.config.tag_category_mapping["artist"] if tag.category == Tag.categories.artist
# we're not interested in artists in the trending list # we're not interested in artists in the trending list
[tag_name, 0] [tag_name, 0]
else else
@@ -317,19 +319,19 @@ class Tag < ApplicationRecord
when :filesize when :filesize
object =~ /\A(\d+(?:\.\d*)?|\d*\.\d+)([kKmM]?)[bB]?\Z/ object =~ /\A(\d+(?:\.\d*)?|\d*\.\d+)([kKmM]?)[bB]?\Z/
size = $1.to_f size = $1.to_f
unit = $2 unit = $2
conversion_factor = case unit conversion_factor = case unit
when /m/i when /m/i
1024 * 1024 1024 * 1024
when /k/i when /k/i
1024 1024
else else
1 1
end end
(size * conversion_factor).to_i (size * conversion_factor).to_i
end end
end end
@@ -429,296 +431,289 @@ class Tag < ApplicationRecord
q[:tag_count] += 1 unless token == "status:deleted" || token =~ /\Alimit:.+\Z/ q[:tag_count] += 1 unless token == "status:deleted" || token =~ /\Alimit:.+\Z/
if token =~ /\A(#{METATAGS}):(.+)\Z/i if token =~ /\A(#{METATAGS}):(.+)\Z/i
case $1.downcase g1 = $1.downcase
g2 = $2
case g1
when "-user" when "-user"
q[:uploader_id_neg] ||= [] q[:uploader_id_neg] ||= []
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:uploader_id_neg] << user_id unless user_id.blank? q[:uploader_id_neg] << user_id unless user_id.blank?
when "user" when "user"
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:uploader_id] = user_id unless user_id.blank? q[:uploader_id] = user_id unless user_id.blank?
when "-approver" when "-approver"
if $2 == "none" if g2 == "none"
q[:approver_id] = "any" q[:approver_id] = "any"
elsif $2 == "any" elsif g2 == "any"
q[:approver_id] = "none" q[:approver_id] = "none"
else else
q[:approver_id_neg] ||= [] q[:approver_id_neg] ||= []
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:approver_id_neg] << user_id unless user_id.blank? q[:approver_id_neg] << user_id unless user_id.blank?
end end
when "approver" when "approver"
if $2 == "none" if g2 == "none"
q[:approver_id] = "none" q[:approver_id] = "none"
elsif $2 == "any" elsif g2 == "any"
q[:approver_id] = "any" q[:approver_id] = "any"
else else
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:approver_id] = user_id unless user_id.blank? q[:approver_id] = user_id unless user_id.blank?
end end
when "flagger" when "flagger"
q[:flagger_ids] ||= [] q[:flagger_ids] ||= []
if $2 == "none" if g2 == "none"
q[:flagger_ids] << "none" q[:flagger_ids] << "none"
elsif $2 == "any" elsif g2 == "any"
q[:flagger_ids] << "any" q[:flagger_ids] << "any"
else else
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:flagger_ids] << user_id unless user_id.blank? q[:flagger_ids] << user_id unless user_id.blank?
end end
when "-flagger" when "-flagger"
if $2 == "none" if g2 == "none"
q[:flagger_ids] ||= [] q[:flagger_ids] ||= []
q[:flagger_ids] << "any" q[:flagger_ids] << "any"
elsif $2 == "any" elsif g2 == "any"
q[:flagger_ids] ||= [] q[:flagger_ids] ||= []
q[:flagger_ids] << "none" q[:flagger_ids] << "none"
else else
q[:flagger_ids_neg] ||= [] q[:flagger_ids_neg] ||= []
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:flagger_ids_neg] << user_id unless user_id.blank? q[:flagger_ids_neg] << user_id unless user_id.blank?
end end
when "appealer" when "appealer"
q[:appealer_ids] ||= [] q[:appealer_ids] ||= []
if $2 == "none" if g2 == "none"
q[:appealer_ids] << "none" q[:appealer_ids] << "none"
elsif $2 == "any" elsif g2 == "any"
q[:appealer_ids] << "any" q[:appealer_ids] << "any"
else else
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:appealer_ids] << user_id unless user_id.blank? q[:appealer_ids] << user_id unless user_id.blank?
end end
when "-appealer" when "-appealer"
if $2 == "none" if g2 == "none"
q[:appealer_ids] ||= [] q[:appealer_ids] ||= []
q[:appealer_ids] << "any" q[:appealer_ids] << "any"
elsif $2 == "any" elsif g2 == "any"
q[:appealer_ids] ||= [] q[:appealer_ids] ||= []
q[:appealer_ids] << "none" q[:appealer_ids] << "none"
else else
q[:appealer_ids_neg] ||= [] q[:appealer_ids_neg] ||= []
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:appealer_ids_neg] << user_id unless user_id.blank? q[:appealer_ids_neg] << user_id unless user_id.blank?
end end
when "commenter", "comm" when "commenter", "comm"
q[:commenter_ids] ||= [] q[:commenter_ids] ||= []
if $2 == "none" if g2 == "none"
q[:commenter_ids] << "none" q[:commenter_ids] << "none"
elsif $2 == "any" elsif g2 == "any"
q[:commenter_ids] << "any" q[:commenter_ids] << "any"
else else
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:commenter_ids] << user_id unless user_id.blank? q[:commenter_ids] << user_id unless user_id.blank?
end end
when "noter" when "noter"
q[:noter_ids] ||= [] q[:noter_ids] ||= []
if $2 == "none" if g2 == "none"
q[:noter_ids] << "none" q[:noter_ids] << "none"
elsif $2 == "any" elsif g2 == "any"
q[:noter_ids] << "any" q[:noter_ids] << "any"
else else
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:noter_ids] << user_id unless user_id.blank? q[:noter_ids] << user_id unless user_id.blank?
end end
when "noteupdater" when "noteupdater"
q[:note_updater_ids] ||= [] q[:note_updater_ids] ||= []
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:note_updater_ids] << user_id unless user_id.blank? q[:note_updater_ids] << user_id unless user_id.blank?
when "artcomm" when "artcomm"
q[:artcomm_ids] ||= [] q[:artcomm_ids] ||= []
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:artcomm_ids] << user_id unless user_id.blank? q[:artcomm_ids] << user_id unless user_id.blank?
when "-pool" when "-pool"
if $2.downcase == "none" if g2.downcase == "none"
q[:pool] = "any" q[:pool] = "any"
elsif $2.downcase == "any" elsif g2.downcase == "any"
q[:pool] = "none" q[:pool] = "none"
elsif $2.downcase == "series" elsif g2.downcase == "series"
q[:tags][:exclude] << "pool:series" q[:tags][:exclude] << "pool:series"
elsif $2.downcase == "collection" elsif g2.downcase == "collection"
q[:tags][:exclude] << "pool:collection" q[:tags][:exclude] << "pool:collection"
else else
q[:tags][:exclude] << "pool:#{Pool.name_to_id($2)}" q[:tags][:exclude] << "pool:#{Pool.name_to_id(g2)}"
end end
when "pool" when "pool"
if $2.downcase == "none" if g2.downcase == "none"
q[:pool] = "none" q[:pool] = "none"
elsif $2.downcase == "any" elsif g2.downcase == "any"
q[:pool] = "any" q[:pool] = "any"
elsif $2.downcase == "series" elsif g2.downcase == "series"
q[:tags][:related] << "pool:series" q[:tags][:related] << "pool:series"
elsif $2.downcase == "collection" elsif g2.downcase == "collection"
q[:tags][:related] << "pool:collection" q[:tags][:related] << "pool:collection"
elsif $2.include?("*") elsif g2.include?("*")
pools = Pool.name_matches($2).select("id").limit(Danbooru.config.tag_query_limit).order("post_count DESC") pools = Pool.name_matches(g2).select("id").limit(Danbooru.config.tag_query_limit).order("post_count DESC")
q[:tags][:include] += pools.map {|pool| "pool:#{pool.id}"} q[:tags][:include] += pools.map {|pool| "pool:#{pool.id}"}
else else
q[:tags][:related] << "pool:#{Pool.name_to_id($2)}" q[:tags][:related] << "pool:#{Pool.name_to_id(g2)}"
end end
when "ordpool" when "ordpool"
pool_id = Pool.name_to_id($2) pool_id = Pool.name_to_id(g2)
q[:tags][:related] << "pool:#{pool_id}" q[:tags][:related] << "pool:#{pool_id}"
q[:ordpool] = pool_id q[:ordpool] = pool_id
when "-favgroup" when "-favgroup"
favgroup_id = FavoriteGroup.name_to_id($2) favgroup_id = FavoriteGroup.name_to_id(g2)
q[:favgroups_neg] ||= [] q[:favgroups_neg] ||= []
q[:favgroups_neg] << favgroup_id q[:favgroups_neg] << favgroup_id
when "favgroup" when "favgroup"
favgroup_id = FavoriteGroup.name_to_id($2) favgroup_id = FavoriteGroup.name_to_id(g2)
q[:favgroups] ||= [] q[:favgroups] ||= []
q[:favgroups] << favgroup_id q[:favgroups] << favgroup_id
when "-fav" when "-fav"
q[:tags][:exclude] << "fav:#{User.name_to_id($2)}" q[:tags][:exclude] << "fav:#{User.name_to_id(g2)}"
when "fav" when "fav"
q[:tags][:related] << "fav:#{User.name_to_id($2)}" q[:tags][:related] << "fav:#{User.name_to_id(g2)}"
when "ordfav" when "ordfav"
user_id = User.name_to_id($2) user_id = User.name_to_id(g2)
q[:tags][:related] << "fav:#{user_id}" q[:tags][:related] << "fav:#{user_id}"
q[:ordfav] = user_id q[:ordfav] = user_id
when "search" when "search"
q[:saved_searches] ||= [] q[:saved_searches] ||= []
q[:saved_searches] << $2 q[:saved_searches] << g2
when "md5" when "md5"
q[:md5] = $2.downcase.split(/,/) q[:md5] = g2.downcase.split(/,/)
when "-rating" when "-rating"
q[:rating_negated] = $2.downcase q[:rating_negated] = g2.downcase
when "rating" when "rating"
q[:rating] = $2.downcase q[:rating] = g2.downcase
when "-locked" when "-locked"
q[:locked_negated] = $2.downcase q[:locked_negated] = g2.downcase
when "locked" when "locked"
q[:locked] = $2.downcase q[:locked] = g2.downcase
when "id" when "id"
q[:post_id] = parse_helper($2) q[:post_id] = parse_helper(g2)
when "-id" when "-id"
q[:post_id_negated] = $2.to_i q[:post_id_negated] = g2.to_i
when "width" when "width"
q[:width] = parse_helper($2) q[:width] = parse_helper(g2)
when "height" when "height"
q[:height] = parse_helper($2) q[:height] = parse_helper(g2)
when "mpixels" when "mpixels"
q[:mpixels] = parse_helper_fudged($2, :float) q[:mpixels] = parse_helper_fudged(g2, :float)
when "ratio" when "ratio"
q[:ratio] = parse_helper($2, :ratio) q[:ratio] = parse_helper(g2, :ratio)
when "score" when "score"
q[:score] = parse_helper($2) q[:score] = parse_helper(g2)
when "favcount" when "favcount"
q[:fav_count] = parse_helper($2) q[:fav_count] = parse_helper(g2)
when "filesize" when "filesize"
q[:filesize] = parse_helper_fudged($2, :filesize) q[:filesize] = parse_helper_fudged(g2, :filesize)
when "source" when "source"
src = $2.gsub(/\A"(.*)"\Z/, '\1') src = g2.gsub(/\A"(.*)"\Z/, '\1')
q[:source] = (src.to_escaped_for_sql_like + "%").gsub(/%+/, '%') q[:source] = (src.to_escaped_for_sql_like + "%").gsub(/%+/, '%')
when "-source" when "-source"
src = $2.gsub(/\A"(.*)"\Z/, '\1') src = g2.gsub(/\A"(.*)"\Z/, '\1')
q[:source_neg] = (src.to_escaped_for_sql_like + "%").gsub(/%+/, '%') q[:source_neg] = (src.to_escaped_for_sql_like + "%").gsub(/%+/, '%')
when "date" when "date"
q[:date] = parse_helper($2, :date) q[:date] = parse_helper(g2, :date)
when "age" when "age"
q[:age] = reverse_parse_helper(parse_helper($2, :age)) q[:age] = reverse_parse_helper(parse_helper(g2, :age))
when "tagcount" when "tagcount"
q[:post_tag_count] = parse_helper($2) q[:post_tag_count] = parse_helper(g2)
when "gentags" when /(#{TagCategory.short_name_regex})tags/
q[:general_tag_count] = parse_helper($2) q["#{TagCategory.short_name_mapping[$1]}_tag_count".to_sym] = parse_helper(g2)
when "arttags"
q[:artist_tag_count] = parse_helper($2)
when "chartags"
q[:character_tag_count] = parse_helper($2)
when "copytags"
q[:copyright_tag_count] = parse_helper($2)
when "parent" when "parent"
q[:parent] = $2.downcase q[:parent] = g2.downcase
when "-parent" when "-parent"
if $2.downcase == "none" if g2.downcase == "none"
q[:parent] = "any" q[:parent] = "any"
elsif $2.downcase == "any" elsif g2.downcase == "any"
q[:parent] = "none" q[:parent] = "none"
else else
q[:parent_neg_ids] ||= [] q[:parent_neg_ids] ||= []
q[:parent_neg_ids] << $2.downcase q[:parent_neg_ids] << g2.downcase
end end
when "child" when "child"
q[:child] = $2.downcase q[:child] = g2.downcase
when "order" when "order"
q[:order] = $2.downcase q[:order] = g2.downcase
when "limit" when "limit"
# Do nothing. The controller takes care of it. # Do nothing. The controller takes care of it.
when "-status" when "-status"
q[:status_neg] = $2.downcase q[:status_neg] = g2.downcase
when "status" when "status"
q[:status] = $2.downcase q[:status] = g2.downcase
when "filetype" when "filetype"
q[:filetype] = $2.downcase q[:filetype] = g2.downcase
when "-filetype" when "-filetype"
q[:filetype_neg] = $2.downcase q[:filetype_neg] = g2.downcase
when "pixiv_id", "pixiv" when "pixiv_id", "pixiv"
q[:pixiv_id] = parse_helper($2) q[:pixiv_id] = parse_helper(g2)
when "upvote" when "upvote"
if CurrentUser.user.is_moderator? if CurrentUser.user.is_moderator?
q[:upvote] = User.name_to_id($2) q[:upvote] = User.name_to_id(g2)
end end
when "downvote" when "downvote"
if CurrentUser.user.is_moderator? if CurrentUser.user.is_moderator?
q[:downvote] = User.name_to_id($2) q[:downvote] = User.name_to_id(g2)
end end
end end

View File

@@ -129,48 +129,24 @@ class PostPresenter < Presenter
@post.humanized_essential_tag_string @post.humanized_essential_tag_string
end end
def categorized_tag_string def categorized_tag_groups
string = [] string = []
if @post.copyright_tags.any? TagCategory.categorized_list.each do |category|
string << @post.copyright_tags.join(" ") if @post.typed_tags(category).any?
string << @post.typed_tags(category).join(" ")
end
end end
string
end
if @post.character_tags.any? def categorized_tag_string
string << @post.character_tags.join(" ") categorized_tag_groups.join(" \n")
end
if @post.artist_tags.any?
string << @post.artist_tags.join(" ")
end
if @post.general_tags.any?
string << @post.general_tags.join(" ")
end
string.join(" \n")
end end
def humanized_categorized_tag_string def humanized_categorized_tag_string
string = [] categorized_tag_groups.flatten.slice(0, 25).join(", ").tr("_", " ")
if @post.copyright_tags.any?
string << @post.copyright_tags
end
if @post.character_tags.any?
string << @post.character_tags
end
if @post.artist_tags.any?
string << @post.artist_tags
end
if @post.general_tags.any?
string << @post.general_tags
end
string.flatten.slice(0, 25).join(", ").tr("_", " ")
end end
def image_html(template) def image_html(template)

View File

@@ -25,40 +25,16 @@ class TagSetPresenter < Presenter
def split_tag_list_html(template, options = {}) def split_tag_list_html(template, options = {})
html = "" html = ""
if copyright_tags.any? TagCategory.split_header_list.each do |category|
html << '<h2>Copyrights</h2>' typetags = typed_tags(category)
html << "<ul>" if typetags.any?
copyright_tags.keys.each do |tag| html << TagCategory.header_mapping[category]
html << build_list_item(tag, template, options) html << "<ul>"
typetags.each do |tag|
html << build_list_item(tag, template, options)
end
html << "</ul>"
end end
html << "</ul>"
end
if character_tags.any?
html << '<h2>Characters</h2>'
html << "<ul>"
character_tags.keys.each do |tag|
html << build_list_item(tag, template, options)
end
html << "</ul>"
end
if artist_tags.any?
html << '<h2>Artist</h2>'
html << "<ul>"
artist_tags.keys.each do |tag|
html << build_list_item(tag, template, options)
end
html << "</ul>"
end
if general_tags.any?
html << '<h1>Tags</h1>'
html << "<ul>"
general_tags.keys.each do |tag|
html << build_list_item(tag, template, options)
end
html << "</ul>"
end end
html.html_safe html.html_safe
@@ -76,20 +52,13 @@ class TagSetPresenter < Presenter
end end
private private
def general_tags def typed_tags(name)
@general_tags ||= categories.select {|k, v| v == Tag.categories.general} @typed_tags ||= {}
end @typed_tags[name] ||= begin
@tags.select do |tag|
def copyright_tags categories[tag] == TagCategory.mapping[name]
@copyright_tags ||= categories.select {|k, v| v == Tag.categories.copyright} end
end end
def character_tags
@character_tags ||= categories.select {|k, v| v == Tag.categories.character}
end
def artist_tags
@artist_tags ||= categories.select {|k, v| v == Tag.categories.artist}
end end
def categories def categories

View File

@@ -8,6 +8,8 @@
<% unless cookies[:dm] %> <% unless cookies[:dm] %>
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<% end %> <% end %>
<meta name="tag-category-names" content="<%= TagCategory.categories %>">
<meta name="short-tag-category-names" content="<%= TagCategory.short_name_list %>">
<meta name="current-user-name" content="<%= CurrentUser.name %>"> <meta name="current-user-name" content="<%= CurrentUser.name %>">
<meta name="current-user-id" content="<%= CurrentUser.id %>"> <meta name="current-user-id" content="<%= CurrentUser.id %>">
<meta name="current-user-can-approve-posts" content="<%= CurrentUser.can_approve_posts? %>"> <meta name="current-user-can-approve-posts" content="<%= CurrentUser.can_approve_posts? %>">

View File

@@ -77,10 +77,10 @@
</div> </div>
<%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
<%= button_tag "General", :id => "related-general-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
<%= button_tag "Artists", :id => "related-artists-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <% TagCategory.related_button_list.each do |category| %>
<%= button_tag "Characters", :id => "related-characters-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <%= button_tag "#{TagCategory.related_button_mapping[category]}", :id => "related-#{category}-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
<%= button_tag "Copyrights", :id => "related-copyrights-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <% end %>
</div> </div>
<div class="input"> <div class="input">

View File

@@ -155,6 +155,7 @@
<% end %> <% end %>
<% content_for(:html_header) do %> <% content_for(:html_header) do %>
<meta name="related-tag-button-list" content="<%= TagCategory.related_button_list %>">
<meta name="description" content="<%= @post.presenter.humanized_tag_string %>"> <meta name="description" content="<%= @post.presenter.humanized_tag_string %>">
<meta name="tags" content="<%= @post.tag_string %>"> <meta name="tags" content="<%= @post.tag_string %>">
<meta name="favorites" content="<%= @post.fav_string %>"> <meta name="favorites" content="<%= @post.fav_string %>">

View File

@@ -3,7 +3,7 @@
<section> <section>
<%= form_tag(related_tag_path, :method => :get) do %> <%= form_tag(related_tag_path, :method => :get) do %>
<%= text_field_tag "query", params[:query], :data => { :autocomplete => "tag" } %> <%= text_field_tag "query", params[:query], :data => { :autocomplete => "tag" } %>
<%= select_tag "category", options_for_select([""] + Danbooru.config.canonical_tag_category_mapping.map{|x| [x.first, x.first.downcase]}, params[:category]) %> <%= select_tag "category", options_for_select([""] + TagCategory.canonical_mapping.map{|x| [x.first, x.first.downcase]}, params[:category]) %>
<%= submit_tag "Show"%> <%= submit_tag "Show"%>
<% end %> <% end %>
</section> </section>

View File

@@ -3,7 +3,7 @@
<%= simple_form_for(:search, method: :get, url: tag_aliases_path, defaults: { required: false }, html: { class: "inline-form" }) do |f| %> <%= simple_form_for(:search, method: :get, url: tag_aliases_path, defaults: { required: false }, html: { class: "inline-form" }) do |f| %>
<%= f.input :name_matches, label: "Name", input_html: { value: params[:search][:name_matches], data: { autocomplete: "tag" } } %> <%= f.input :name_matches, label: "Name", input_html: { value: params[:search][:name_matches], data: { autocomplete: "tag" } } %>
<%= f.input :status, label: "Status", collection: ["", "Approved", "Pending"], selected: params[:search][:status] %> <%= f.input :status, label: "Status", collection: ["", "Approved", "Pending"], selected: params[:search][:status] %>
<%= f.input :category, label: "Category", collection: Danbooru.config.canonical_tag_category_mapping.to_a, include_blank: true, selected: params[:search][:category] %> <%= f.input :category, label: "Category", collection: TagCategory.canonical_mapping.to_a, include_blank: true, selected: params[:search][:category] %>
<%= f.input :order, label: "Order", collection: [%w[Status status], %w[Recently\ created created_at], %w[Recently\ updated updated_at], %w[Name name], %w[Tag\ count tag_count]], selected: params[:search][:order] %> <%= f.input :order, label: "Order", collection: [%w[Status status], %w[Recently\ created created_at], %w[Recently\ updated updated_at], %w[Name name], %w[Tag\ count tag_count]], selected: params[:search][:order] %>
<%= f.submit "Search" %> <%= f.submit "Search" %>
<% end %> <% end %>

View File

@@ -3,7 +3,7 @@
<%= simple_form_for(:search, method: :get, url: tag_implications_path, defaults: { required: false }, html: { class: "inline-form" }) do |f| %> <%= simple_form_for(:search, method: :get, url: tag_implications_path, defaults: { required: false }, html: { class: "inline-form" }) do |f| %>
<%= f.input :name_matches, label: "Name", input_html: { value: params[:search][:name_matches], data: { autocomplete: "tag" } } %> <%= f.input :name_matches, label: "Name", input_html: { value: params[:search][:name_matches], data: { autocomplete: "tag" } } %>
<%= f.input :status, label: "Status", collection: ["", "Approved", "Pending"], selected: params[:search][:status] %> <%= f.input :status, label: "Status", collection: ["", "Approved", "Pending"], selected: params[:search][:status] %>
<%= f.input :category, label: "Category", collection: Danbooru.config.canonical_tag_category_mapping.to_a, include_blank: true, selected: params[:search][:category] %> <%= f.input :category, label: "Category", collection: TagCategory.canonical_mapping.to_a, include_blank: true, selected: params[:search][:category] %>
<%= f.input :order, label: "Order", collection: [%w[Status status], %w[Recently\ created created_at], %w[Recently\ updated updated_at], %w[Name name], %w[Tag\ count tag_count]], selected: params[:search][:order] %> <%= f.input :order, label: "Order", collection: [%w[Status status], %w[Recently\ created created_at], %w[Recently\ updated updated_at], %w[Name name], %w[Tag\ count tag_count]], selected: params[:search][:order] %>
<%= f.submit "Search" %> <%= f.submit "Search" %>
<% end %> <% end %>

View File

@@ -1,6 +1,6 @@
<%= simple_form_for(:search, url: tags_path, method: :get, defaults: { required: false }, html: { class: "inline-form" }) do |f| %> <%= simple_form_for(:search, url: tags_path, method: :get, defaults: { required: false }, html: { class: "inline-form" }) do |f| %>
<%= f.input :name_matches, label: "Name", hint: "Use * for wildcard", input_html: { value: params[:search][:name_matches], data: { autocomplete: "tag" } } %> <%= f.input :name_matches, label: "Name", hint: "Use * for wildcard", input_html: { value: params[:search][:name_matches], data: { autocomplete: "tag" } } %>
<%= f.input :category, label: "Category", collection: Danbooru.config.canonical_tag_category_mapping.to_a, include_blank: true,selected: params[:search][:category] %> <%= f.input :category, label: "Category", collection: TagCategory.canonical_mapping.to_a, include_blank: true,selected: params[:search][:category] %>
<%= f.input :order, collection: [%w[Newest date], %w[Count count], %w[Name name]], include_blank: false, selected: params[:search][:order] %> <%= f.input :order, collection: [%w[Newest date], %w[Count count], %w[Name name]], include_blank: false, selected: params[:search][:order] %>
<%= f.input :hide_empty, label: "Hide empty?", collection: %w[yes no], selected: params[:search][:hide_empty] %> <%= f.input :hide_empty, label: "Hide empty?", collection: %w[yes no], selected: params[:search][:hide_empty] %>
<%= f.input :has_wiki, label: "Has wiki?", collection: %w[yes no], include_blank: true, selected: params[:search][:has_wiki] %> <%= f.input :has_wiki, label: "Has wiki?", collection: %w[yes no], include_blank: true, selected: params[:search][:has_wiki] %>

View File

@@ -6,7 +6,7 @@
<% if @tag.is_locked? %> <% if @tag.is_locked? %>
<p>This tag is category locked</p> <p>This tag is category locked</p>
<% else %> <% else %>
<%= f.input :category, :collection => Danbooru.config.canonical_tag_category_mapping.to_a, :include_blank => false %> <%= f.input :category, :collection => TagCategory.canonical_mapping.to_a, :include_blank => false %>
<% end %> <% end %>
<% if CurrentUser.is_moderator? %> <% if CurrentUser.is_moderator? %>

View File

@@ -109,10 +109,10 @@
</div> </div>
<%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <%= button_tag "Related tags", :id => "related-tags-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
<%= button_tag "General", :id => "related-general-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
<%= button_tag "Artists", :id => "related-artists-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <% TagCategory.related_button_list.each do |category| %>
<%= button_tag "Characters", :id => "related-characters-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <%= button_tag "#{TagCategory.related_button_mapping[category]}", :id => "related-#{category}-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %>
<%= button_tag "Copyrights", :id => "related-copyrights-button", :type => "button", :class => "ui-button ui-widget ui-corner-all sub gradient" %> <% end %>
</div> </div>
<div class="input"> <div class="input">
@@ -141,4 +141,8 @@
Upload - <%= Danbooru.config.app_name %> Upload - <%= Danbooru.config.app_name %>
<% end %> <% end %>
<% content_for(:html_header) do %>
<meta name="related-tag-button-list" content="<%= Danbooru.config.related_tag_button_list %>">
<% end %>
<%= render "posts/partials/common/secondary_links" %> <%= render "posts/partials/common/secondary_links" %>

View File

@@ -214,46 +214,93 @@ module Danbooru
"albert" "albert"
end end
# Returns a hash mapping various tag categories to a numerical value. #TAG CONFIGURATION
# Be sure to update the reverse_tag_category_mapping also.
def tag_category_mapping
@tag_category_mapping ||= {
"general" => 0,
"gen" => 0,
"artist" => 1, #Full tag configuration info for all tags
"art" => 1, def full_tag_config_info
@full_tag_category_mapping ||= {
"copyright" => 3, "general" => {
"copy" => 3, "category" => 0,
"co" => 3, "short" => "gen",
"extra" => [],
"character" => 4, "header" => "<h1>Tags</h1>",
"char" => 4, "humanized" => nil,
"ch" => 4 "relatedbutton" => "General"
},
"character" => {
"category" => 4,
"short" => "char",
"extra" => ["ch"],
"header" => "<h2>Characters</h2>",
"humanized" => {
"slice" => 5,
"exclusion" => [],
"regexmap" => /^(.+?)(?:_\(.+\))?$/,
"formatstr" => "%s"
},
"relatedbutton" => "Characters"
},
"copyright" => {
"category" => 3,
"short" => "copy",
"extra" => ["co"],
"header" => "<h2>Copyrights</h2>",
"humanized" => {
"slice" => 5,
"exclusion" => [],
"regexmap" => //,
"formatstr" => "(%s)"
},
"relatedbutton" => "Copyrights"
},
"artist" => {
"category" => 1,
"short" => "art",
"extra" => [],
"header" => "<h2>Artist</h2>",
"humanized" => {
"slice" => 0,
"exclusion" => %w(banned_artist),
"regexmap" => //,
"formatstr" => "drawn by %s"
},
"relatedbutton" => "Artists"
},
"meta" => {
"category" => 5,
"short" => "meta",
"extra" => [],
"header" => "<h2>Meta</h2>",
"humanized" => nil,
"relatedbutton" => nil
}
} }
end end
def canonical_tag_category_mapping #TAG ORDERS
@canonical_tag_category_mapping ||= {
"General" => 0, #Sets the order of the humanized essential tag string (models/post.rb)
"Artist" => 1, def humanized_tag_category_list
"Copyright" => 3, @humanized_tag_category_list ||= ["character","copyright","artist"]
"Character" => 4
}
end end
# Returns a hash maping numerical category values to their #Sets the order of the split tag header list (presenters/tag_set_presenter.rb)
# string equivalent. Be sure to update the tag_category_mapping also. def split_tag_header_list
def reverse_tag_category_mapping @split_tag_header_list ||= ["copyright","character","artist","general","meta"]
@reverse_tag_category_mapping ||= {
0 => "General",
1 => "Artist",
3 => "Copyright",
4 => "Character"
}
end end
#Sets the order of the categorized tag string (presenters/post_presenter.rb)
def categorized_tag_list
@categorized_tag_list ||= ["copyright","character","artist","meta","general"]
end
#Sets the order of the related tag buttons (javascripts/related_tag.js)
def related_tag_button_list
@related_tag_button_list ||= ["general","artist","character","copyright"]
end
#END TAG
# If enabled, users must verify their email addresses. # If enabled, users must verify their email addresses.
def enable_email_verification? def enable_email_verification?
false false

View File

@@ -0,0 +1,7 @@
class AddTagCountMetaToPosts < ActiveRecord::Migration
def change
Post.without_timeout do
add_column :posts, :tag_count_meta, :integer, default: 0, null: false
end
end
end

View File

@@ -2776,7 +2776,8 @@ CREATE TABLE posts (
pixiv_id integer, pixiv_id integer,
last_commented_at timestamp without time zone, last_commented_at timestamp without time zone,
has_active_children boolean DEFAULT false, has_active_children boolean DEFAULT false,
bit_flags bigint DEFAULT 0 NOT NULL bit_flags bigint DEFAULT 0 NOT NULL,
tag_count_meta integer DEFAULT 0 NOT NULL
); );
@@ -7518,3 +7519,5 @@ INSERT INTO schema_migrations (version) VALUES ('20170709190409');
INSERT INTO schema_migrations (version) VALUES ('20170914200122'); INSERT INTO schema_migrations (version) VALUES ('20170914200122');
INSERT INTO schema_migrations (version) VALUES ('20171106075030');

View File

@@ -61,6 +61,7 @@ class TagTest < ActiveSupport::TestCase
assert_equal(1, Tag.categories.artist) assert_equal(1, Tag.categories.artist)
assert_equal(3, Tag.categories.copyright) assert_equal(3, Tag.categories.copyright)
assert_equal(4, Tag.categories.character) assert_equal(4, Tag.categories.character)
assert_equal(5, Tag.categories.meta)
end end
should "have a regular expression for matching category names and shortcuts" do should "have a regular expression for matching category names and shortcuts" do
@@ -74,6 +75,7 @@ class TagTest < ActiveSupport::TestCase
assert_match(regexp, "character") assert_match(regexp, "character")
assert_match(regexp, "char") assert_match(regexp, "char")
assert_match(regexp, "ch") assert_match(regexp, "ch")
assert_match(regexp, "meta")
assert_no_match(regexp, "c") assert_no_match(regexp, "c")
assert_no_match(regexp, "woodle") assert_no_match(regexp, "woodle")
end end
@@ -83,6 +85,7 @@ class TagTest < ActiveSupport::TestCase
assert_equal(0, Tag.categories.value_for("gen")) assert_equal(0, Tag.categories.value_for("gen"))
assert_equal(1, Tag.categories.value_for("artist")) assert_equal(1, Tag.categories.value_for("artist"))
assert_equal(1, Tag.categories.value_for("art")) assert_equal(1, Tag.categories.value_for("art"))
assert_equal(5, Tag.categories.value_for("meta"))
assert_equal(0, Tag.categories.value_for("unknown")) assert_equal(0, Tag.categories.value_for("unknown"))
end end
end end
@@ -215,7 +218,7 @@ class TagTest < ActiveSupport::TestCase
should_not allow_value("café").for(:name).on(:create) should_not allow_value("café").for(:name).on(:create)
should_not allow_value("東方").for(:name).on(:create) should_not allow_value("東方").for(:name).on(:create)
metatags = Tag::METATAGS.split("|") + Tag::SUBQUERY_METATAGS.split("|") + Danbooru.config.tag_category_mapping.keys metatags = Tag::METATAGS.split("|") + Tag::SUBQUERY_METATAGS.split("|") + TagCategory.mapping.keys
metatags.split("|").each do |metatag| metatags.split("|").each do |metatag|
should_not allow_value("#{metatag}:foo").for(:name).on(:create) should_not allow_value("#{metatag}:foo").for(:name).on(:create)
end end