Favorite groups
This commit is contained in:
211
app/models/favorite_group.rb
Normal file
211
app/models/favorite_group.rb
Normal file
@@ -0,0 +1,211 @@
|
||||
require 'ostruct'
|
||||
|
||||
class FavoriteGroup < ActiveRecord::Base
|
||||
validates_uniqueness_of :name, :case_sensitive => false, :scope => :creator_id
|
||||
validates_format_of :name, :with => /\A[^,]+\Z/, :message => "cannot have commas"
|
||||
belongs_to :creator, :class_name => "User"
|
||||
before_validation :normalize_post_ids
|
||||
before_validation :normalize_name
|
||||
before_validation :initialize_creator, :on => :create
|
||||
before_validation :strip_name
|
||||
validate :creator_can_create_favorite_groups, :on => :create
|
||||
validate :validate_number_of_posts
|
||||
after_create :synchronize!
|
||||
attr_accessible :name, :post_ids, :post_id_array, :as => [:member, :gold, :platinum, :builder, :contributor, :janitor, :moderator, :admin, :default]
|
||||
|
||||
module SearchMethods
|
||||
def for_creator(user_id)
|
||||
where("favorite_groups.creator_id = ?", user_id)
|
||||
end
|
||||
|
||||
def named(name)
|
||||
where("lower(name) = ?", name.to_s.mb_chars.downcase.strip)
|
||||
end
|
||||
|
||||
def name_matches(name)
|
||||
name = name.tr(" ", "_")
|
||||
name = "*#{name}*" unless name =~ /\*/
|
||||
where("name ilike ? escape E'\\\\'", name.to_escaped_for_sql_like)
|
||||
end
|
||||
|
||||
def search(params)
|
||||
q = where("true")
|
||||
params = {} if params.blank?
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||
elsif params[:creator_name].present?
|
||||
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].tr(" ", "_").mb_chars.downcase)
|
||||
else
|
||||
q = q.where("creator_id = ?", CurrentUser.user.id)
|
||||
end
|
||||
|
||||
if params[:name_matches].present?
|
||||
q = q.name_matches(params[:name_matches])
|
||||
end
|
||||
|
||||
q
|
||||
end
|
||||
end
|
||||
|
||||
extend SearchMethods
|
||||
|
||||
def self.name_to_id(name)
|
||||
if name =~ /^\d+$/
|
||||
name.to_i
|
||||
else
|
||||
select_value_sql("SELECT id FROM favorite_groups WHERE lower(name) = ? AND creator_id = ?", name.to_s.mb_chars.downcase.tr(" ", "_"), CurrentUser.user.id).to_i
|
||||
end
|
||||
end
|
||||
|
||||
def creator_can_create_favorite_groups
|
||||
if creator.favorite_group_count >= creator.favorite_group_limit
|
||||
error = "You can only keep up to #{creator.favorite_group_limit} favorite groups."
|
||||
if !CurrentUser.user.is_platinum?
|
||||
error += " Upgrade your account to create more."
|
||||
end
|
||||
self.errors.add(:base, error)
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def validate_number_of_posts
|
||||
if post_id_array.size > 10_000
|
||||
self.errors.add(:base, "Favorite groups can have up to 10,000 posts each")
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def normalize_post_ids
|
||||
self.post_ids = post_ids.scan(/\d+/).uniq.join(" ")
|
||||
end
|
||||
|
||||
def normalize_name
|
||||
self.name = name.gsub(/\s+/, "_")
|
||||
end
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
end
|
||||
|
||||
def strip_name
|
||||
self.name = name.to_s.strip
|
||||
end
|
||||
|
||||
def pretty_name
|
||||
name.tr("_", " ")
|
||||
end
|
||||
|
||||
def posts(options = {})
|
||||
offset = options[:offset] || 0
|
||||
limit = options[:limit] || Danbooru.config.posts_per_page
|
||||
slice = post_id_array.slice(offset, limit)
|
||||
if slice && slice.any?
|
||||
slice.map do |id|
|
||||
begin
|
||||
Post.find(id)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
# swallow
|
||||
end
|
||||
end.compact
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def post_id_array
|
||||
@post_id_array ||= post_ids.scan(/\d+/).map(&:to_i)
|
||||
end
|
||||
|
||||
def post_id_array=(array)
|
||||
self.post_ids = array.join(" ")
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
def post_id_array_was
|
||||
@post_id_array_was ||= post_ids_was.scan(/\d+/).map(&:to_i)
|
||||
end
|
||||
|
||||
def clear_post_id_array
|
||||
@post_id_array = nil
|
||||
@post_id_array_was = nil
|
||||
end
|
||||
|
||||
def synchronize
|
||||
added = post_id_array - post_id_array_was
|
||||
removed = post_id_array_was - post_id_array
|
||||
|
||||
normalize_post_ids
|
||||
clear_post_id_array
|
||||
self.post_count = post_id_array.size
|
||||
end
|
||||
|
||||
def synchronize!
|
||||
synchronize
|
||||
save
|
||||
end
|
||||
|
||||
def add!(post)
|
||||
return if contains?(post.id)
|
||||
|
||||
update_attributes(:post_ids => add_number_to_string(post.id, post_ids), :post_count => post_count + 1)
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
def remove!(post)
|
||||
return unless contains?(post.id)
|
||||
|
||||
update_attributes(:post_ids => remove_number_from_string(post.id, post_ids), :post_count => post_count - 1)
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
def add_number_to_string(number, string)
|
||||
"#{string} #{number}"
|
||||
end
|
||||
|
||||
def remove_number_from_string(number, string)
|
||||
string.gsub(/(?:\A| )#{number}(?:\Z| )/, " ")
|
||||
end
|
||||
|
||||
def neighbors(post)
|
||||
@neighbor_posts ||= begin
|
||||
post_ids =~ /\A#{post.id} (\d+)|(\d+) #{post.id} (\d+)|(\d+) #{post.id}\Z/
|
||||
|
||||
if $2 && $3
|
||||
OpenStruct.new(:previous => $2.to_i, :next => $3.to_i)
|
||||
elsif $1
|
||||
OpenStruct.new(:next => $1.to_i)
|
||||
elsif $4
|
||||
OpenStruct.new(:previous => $4.to_i)
|
||||
else
|
||||
OpenStruct.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def reload(options = {})
|
||||
super
|
||||
@neighbor_posts = nil
|
||||
clear_post_id_array
|
||||
end
|
||||
|
||||
def last_page
|
||||
(post_count / CurrentUser.user.per_page.to_f).ceil
|
||||
end
|
||||
|
||||
def strip_name
|
||||
self.name = name.to_s.strip
|
||||
end
|
||||
|
||||
def contains?(post_id)
|
||||
post_ids =~ /(?:\A| )#{post_id}(?:\Z| )/
|
||||
end
|
||||
|
||||
def editable_by?(user)
|
||||
creator_id == user.id
|
||||
end
|
||||
end
|
||||
@@ -629,7 +629,7 @@ class Post < ActiveRecord::Base
|
||||
|
||||
def filter_metatags(tags)
|
||||
@pre_metatags, tags = tags.partition {|x| x =~ /\A(?:rating|parent|-parent):/i}
|
||||
@post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|newpool|fav|child):/i}
|
||||
@post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|newpool|fav|child|-favgroup|favgroup):/i}
|
||||
apply_pre_metatags
|
||||
return tags
|
||||
end
|
||||
@@ -669,6 +669,22 @@ class Post < ActiveRecord::Base
|
||||
child = Post.find($1)
|
||||
child.parent_id = id
|
||||
child.save
|
||||
|
||||
when /^-favgroup:(\d+)$/i
|
||||
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
||||
favgroup.remove!(self) if favgroup
|
||||
|
||||
when /^-favgroup:(.+)$/i
|
||||
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
||||
favgroup.remove!(self) if favgroup
|
||||
|
||||
when /^favgroup:(\d+)$/i
|
||||
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
||||
favgroup.add!(self) if favgroup
|
||||
|
||||
when /^favgroup:(.+)$/i
|
||||
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
||||
favgroup.add!(self) if favgroup
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -821,6 +837,14 @@ class Post < ActiveRecord::Base
|
||||
def favorited_users
|
||||
favorited_user_ids.map {|id| User.find(id)}
|
||||
end
|
||||
|
||||
def favorite_groups
|
||||
@favorite_groups ||= begin
|
||||
CurrentUser.user.favorite_groups.select do |favgroup|
|
||||
favgroup.contains?(self.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module UploaderMethods
|
||||
@@ -1578,6 +1602,7 @@ class Post < ActiveRecord::Base
|
||||
super
|
||||
reset_tag_array_cache
|
||||
@pools = nil
|
||||
@favorite_groups = nil
|
||||
@tag_categories = nil
|
||||
@typed_tags = nil
|
||||
self
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Tag < ActiveRecord::Base
|
||||
METATAGS = "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-pool|pool|ordpool|-fav|fav|ordfav|sub|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"
|
||||
METATAGS = "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-pool|pool|ordpool|favgroup|-fav|fav|ordfav|sub|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"
|
||||
SUBQUERY_METATAGS = "commenter|comm|noter|noteupdater|artcomm"
|
||||
attr_accessible :category, :as => [:moderator, :janitor, :contributor, :gold, :member, :anonymous, :default, :builder, :admin]
|
||||
attr_accessible :is_locked, :as => [:moderator, :janitor, :admin]
|
||||
@@ -460,6 +460,10 @@ class Tag < ActiveRecord::Base
|
||||
q[:tags][:related] << "pool:#{pool_id}"
|
||||
q[:ordpool] = pool_id
|
||||
|
||||
when "favgroup"
|
||||
favgroup_id = FavoriteGroup.name_to_id($2)
|
||||
q[:favgroup] = favgroup_id
|
||||
|
||||
when "-fav"
|
||||
q[:tags][:exclude] << "fav:#{User.name_to_id($2)}"
|
||||
|
||||
|
||||
@@ -253,6 +253,10 @@ class User < ActiveRecord::Base
|
||||
def remove_favorite!(post)
|
||||
Favorite.remove(post, self)
|
||||
end
|
||||
|
||||
def favorite_groups
|
||||
FavoriteGroup.for_creator(CurrentUser.user.id)
|
||||
end
|
||||
end
|
||||
|
||||
module LevelMethods
|
||||
@@ -541,7 +545,17 @@ class User < ActiveRecord::Base
|
||||
10_000
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def favorite_group_limit
|
||||
if is_platinum?
|
||||
10
|
||||
elsif is_gold?
|
||||
5
|
||||
else
|
||||
3
|
||||
end
|
||||
end
|
||||
|
||||
def api_hourly_limit
|
||||
if is_platinum? && api_key.present?
|
||||
20_000
|
||||
@@ -634,6 +648,10 @@ class User < ActiveRecord::Base
|
||||
Comment.for_creator(id).count
|
||||
end
|
||||
|
||||
def favorite_group_count
|
||||
FavoriteGroup.for_creator(id).count
|
||||
end
|
||||
|
||||
def appeal_count
|
||||
PostAppeal.for_creator(id).count
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user