diff --git a/Gemfile b/Gemfile index 70cc30fb0..86300e1e9 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ group :test do gem "faker" end -gem "rails", "3.0.0.beta" +gem "rails", "3.0.0.beta3" gem "pg" gem "memcache-client", :require => "memcache" gem "imagesize", :require => "image_size" diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 0eca12f53..4171b4be3 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,7 +1,27 @@ class CommentsController < ApplicationController + respond_to :html, :xml, :json + def index end def update + @comment = Comment.find(params[:id]) + @comment.update_attributes(params[:comment]) + respond_with(@comment) + end + + def create + @comment = Comment.new(params[:comment]) + @comment.post_id = params[:comment][:post_id] + @comment.creator_id = @current_user.id + @comment.ip_addr = request.remote_ip + @comment.score = 0 + @comment.save + respond_with(@comment) do |format| + format.html do + flash[:notice] = "Comment posted" + redirect_to posts_path(@comment.post) + end + end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2acd1302e..c0157128f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -9,6 +9,10 @@ module ApplicationHelper content_tag("li", link_to(text, url, options), :class => klass) end + def format_text(text, options = {}) + DText.parse(text) + end + protected def nav_link_match(controller, url) url =~ case controller diff --git a/app/helpers/post_helper.rb b/app/helpers/post_helper.rb deleted file mode 100644 index 01357d239..000000000 --- a/app/helpers/post_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module PostHelper -end diff --git a/app/helpers/posts_helper.rb b/app/helpers/posts_helper.rb new file mode 100644 index 000000000..db1e2f370 --- /dev/null +++ b/app/helpers/posts_helper.rb @@ -0,0 +1,27 @@ +module PostsHelper + def image_dimensions(post, current_user) + if post.is_image? + "(#{post.image_width_for(current_user)}x#{post.image_height_for(current_user)})" + else + "" + end + end + + def image_dimension_menu(post, current_user) + html = "" + file_size = number_to_human_size(post.file_size) + original_dimensions = post.is_image? ? "(#{post.image_width}x#{post.image_height})" : nil + large_dimensions = post.has_large? ? "(#{post.large_image_width}x#{post.large_image_height})" : nil + medium_dimensions = post.has_medium? ? "(#{post.medium_image_width}x#{post.medium_image_height})" : nil + current_dimensions = "(#{post.image_width_for(current_user)}x#{post.image_height_for(current_user)})" + html << %{
' + end + + when "[/quote]" + if options[:inline] + "" + else + '' + end + + else + '
' + parse_inline(block) + "
" + end + end + + html.join("").html_safe + end +end + diff --git a/app/logical/related_tag_calculator.rb b/app/logical/related_tag_calculator.rb index f16bc8814..ff680fe4e 100644 --- a/app/logical/related_tag_calculator.rb +++ b/app/logical/related_tag_calculator.rb @@ -1,26 +1,34 @@ class RelatedTagCalculator def find_tags(tag, limit) - ActiveRecord::Base.select_values_sql("SELECT tag_string FROM posts WHERE tag_index @@ to_tsquery('danbooru', ?) ORDER BY id DESC LIMIT ?", tag, limit) + Post.find_by_tags(tag, :limit => limit, :select => "posts.tag_string", :order => "posts.md5").map(&:tag_string) end def calculate_from_sample(name, limit, category_constraint = nil) counts = Hash.new {|h, k| h[k] = 0} + case category_constraint + when Tag.categories.artist + limit *= 5 + + when Tag.categories.copyright + limit *= 4 + + when Tag.categories.character + limit *= 3 + end + find_tags(name, limit).each do |tags| tag_array = Tag.scan_tags(tags) if category_constraint - categories = Tag.categories_for(tag_array) - tag_array.each do |tag| - if categories[tag] == category_constraint && tag != name + category = Tag.category_for(tag) + if category == category_constraint counts[tag] += 1 end end else tag_array.each do |tag| - if tag != name - counts[tag] += 1 - end + counts[tag] += 1 end end end @@ -28,7 +36,11 @@ class RelatedTagCalculator counts end + def convert_hash_to_array(hash) + hash.to_a.sort_by {|x| -x[1]}.slice(0, 25) + end + def convert_hash_to_string(hash) - hash.to_a.sort_by {|x| -x[1]}.flatten.join(" ") + convert_hash_to_array(hash).flatten.join(" ") end end diff --git a/app/models/comment.rb b/app/models/comment.rb index f81aaa8a7..e31f5f9dd 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,5 @@ -class Comment < ActiveRecord::Base +class Comment < ActiveRecord::Base + validate :validate_creator_is_not_limited validates_format_of :body, :with => /\S/, :message => 'has no content' belongs_to :post belongs_to :creator, :class_name => "User" @@ -6,35 +7,24 @@ class Comment < ActiveRecord::Base after_save :update_last_commented_at after_destroy :update_last_commented_at attr_accessible :body - attr_accessor :do_not_bump_post scope :recent, :order => "comments.id desc", :limit => 6 scope :search_body, lambda {|query| where("body_index @@ plainto_tsquery(?)", query).order("comments.id DESC")} scope :hidden, lambda {|user| where("score < ?", user.comment_threshold)} + def creator_name + User.find_name(creator_id) + end + + def validate_creator_is_not_limited + creator.is_privileged? || Comment.where("creator_id = ? AND created_at >= ?", creator_id, 1.hour.ago).count < 5 + end + def update_last_commented_at - return if do_not_bump_post - comment_count = Comment.where(["post_id = ?", post_id]).count - if comment_count <= Danbooru.config.comment_threshold + if Comment.where(["post_id = ?", post_id]).count <= Danbooru.config.comment_threshold execute_sql("UPDATE posts SET last_commented_at = ? WHERE id = ?", created_at, post_id) end end - - def can_be_voted_by?(user) - !votes.exists?(["user_id = ?", user.id]) - end - - def vote!(user, is_positive) - if can_be_voted_by?(user) - if is_positive - increment!(:score) - else - decrement!(:score) - end - - votes.create(:user_id => user.id) - else - raise CommentVote::Error.new("You have already voted for this comment") - end - end end + +Comment.connection.extend(PostgresExtensions) diff --git a/app/models/comment_vote.rb b/app/models/comment_vote.rb index 7d30fc284..33f4ae573 100644 --- a/app/models/comment_vote.rb +++ b/app/models/comment_vote.rb @@ -1,10 +1,21 @@ class CommentVote < ActiveRecord::Base class Error < Exception ; end + attr_accessor :is_positive + validates_uniqueness_of :ip_addr, :scope => :comment_id belongs_to :comment belongs_to :user + after_save :update_comment_score def self.prune! destroy_all(["created_at < ?", 14.days.ago]) end + + def update_comment_score + if is_positive + comment.increment!(:score) + else + comment.decrement!(:score) + end + end end diff --git a/app/models/ip_ban.rb b/app/models/ip_ban.rb index c16bc1804..4de36f4a9 100644 --- a/app/models/ip_ban.rb +++ b/app/models/ip_ban.rb @@ -6,4 +6,24 @@ class IpBan < ActiveRecord::Base def self.is_banned?(ip_addr) exists?(["ip_addr = ?", ip_addr]) end + + def self.search(user_ids) + comments = count_by_ip_addr("comments", user_ids, "creator_id") + posts = count_by_ip_addr("post_versions", user_ids, "updater_id") + notes = count_by_ip_addr("note_versions", user_ids, "updater_id") + pools = count_by_ip_addr("pool_updates", user_ids, "updater_id") + wiki_pages = count_by_ip_addr("wiki_page_versions", user_ids, "updater_id") + + return { + "comments" => comments, + "posts" => posts, + "notes" => notes, + "pools" => pools, + "wiki_pages" => wiki_pages + } + end + + def self.count_by_ip_addr(table, user_ids, user_id_field = "user_id") + select_all_sql("SELECT ip_addr, count(*) FROM #{table} WHERE #{user_id_field} IN (?) GROUP BY ip_addr ORDER BY count(*) DESC", user_ids) + end end diff --git a/app/models/post.rb b/app/models/post.rb index 21588e8ce..5cc253bd6 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,5 +1,5 @@ class Post < ActiveRecord::Base - attr_accessor :updater_id, :updater_ip_addr, :old_tag_string + attr_accessor :updater_id, :updater_ip_addr, :old_tag_string, :should_create_pool after_destroy :delete_files after_destroy :delete_favorites after_destroy :update_tag_post_counts @@ -17,6 +17,7 @@ class Post < ActiveRecord::Base has_many :versions, :class_name => "PostVersion", :dependent => :destroy has_many :votes, :class_name => "PostVote", :dependent => :destroy has_many :notes, :dependent => :destroy + has_many :comments validates_presence_of :updater_id, :updater_ip_addr validates_uniqueness_of :md5 attr_accessible :source, :rating, :tag_string, :old_tag_string, :updater_id, :updater_ip_addr, :last_noted_at @@ -136,7 +137,7 @@ class Post < ActiveRecord::Base def medium_image_height ratio = Danbooru.config.medium_image_width.to_f / image_width.to_f if ratio < 1 - image_height * ratio + (image_height * ratio).to_i else image_height end @@ -145,7 +146,7 @@ class Post < ActiveRecord::Base def large_image_height ratio = Danbooru.config.large_image_width.to_f / image_width.to_f if ratio < 1 - image_height * ratio + (image_height * ratio).to_i else image_height end @@ -515,10 +516,10 @@ class Post < ActiveRecord::Base relation = relation.order("posts.image_width * posts.image_height / 1000000.0, posts.id DESC") when "portrait" - relation = relation.order("1.0 * image_width / GREATEST(1, image_height), posts.id DESC") + relation = relation.order("1.0 * posts.image_width / GREATEST(1, posts.image_height), posts.id DESC") when "landscape" - relation = relation.order("1.0 * image_width / GREATEST(1, image_height) DESC, posts.id DESC") + relation = relation.order("1.0 * posts.image_width / GREATEST(1, posts.image_height) DESC, posts.id DESC") when "filesize", "filesize_desc" relation = relation.order("posts.file_size DESC") @@ -538,6 +539,10 @@ class Post < ActiveRecord::Base relation = relation.offset(options[:offset]) end + if options[:select] + relation = relation.select(options[:select]) + end + relation end end @@ -649,3 +654,5 @@ class Post < ActiveRecord::Base @presenter ||= PostPresenter.new(self) end end + +Post.connection.extend(PostgresExtensions) diff --git a/app/models/post_vote.rb b/app/models/post_vote.rb index bafbcce27..eaff64e89 100644 --- a/app/models/post_vote.rb +++ b/app/models/post_vote.rb @@ -1,5 +1,16 @@ class PostVote < ActiveRecord::Base class Error < Exception ; end + attr_accessor :is_positive + validates_uniqueness_of :ip_addr, :scope => :post_id + after_save :update_post_score belongs_to :post + + def update_post_score + if is_positive + post.increment!(:score) + else + post.decrement!(:score) + end + end end diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index 4c6dc7d1d..472b7444c 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -2,27 +2,20 @@ class PostPresenter < Presenter def initialize(post) @post = post end - - def tag_list_html - end - + def image_html(template, current_user) - return "" if @post.is_deleted? && !current_user.is_janitor? + return template.content_tag("p", "This image was deleted.") if @post.is_deleted? && !current_user.is_janitor? + return template.content_tag("p", "You need a privileged account to see this image.") if !Danbooru.config.can_see_post?(@post, current_user) if @post.is_flash? - template.render(:partial => "posts/flash", :locals => {:post => @post}) + template.render(:partial => "posts/partials/show/flash", :locals => {:post => @post}) elsif @post.is_image? - template.image_tag( - @post.file_url_for(current_user), - :alt => @post.tag_string, - :width => @post.image_width_for(current_user), - :height => @post.image_height_for(current_user), - "data-original-width" => @post.image_width, - "data-original-height" => @post.image_height - ) + template.render(:partial => "posts/partials/show/image", :locals => {:post => @post}) end end - def note_html + def tag_list_html(template, current_user) + @tag_set_presenter ||= TagSetPresenter.new(@post.tag_array) + @tag_set_presenter.tag_list_html(template, :show_extra_links => current_user.is_privileged?) end end diff --git a/app/presenters/presenter.rb b/app/presenters/presenter.rb index 08eeaf636..3a294dcb4 100644 --- a/app/presenters/presenter.rb +++ b/app/presenters/presenter.rb @@ -2,4 +2,8 @@ class Presenter def h(s) CGI.escapeHTML(s) end + + def u(s) + URI.escape(s) + end end diff --git a/app/presenters/tag_set_presenter.rb b/app/presenters/tag_set_presenter.rb index ebf8a7f2f..da6c7868f 100644 --- a/app/presenters/tag_set_presenter.rb +++ b/app/presenters/tag_set_presenter.rb @@ -5,36 +5,42 @@ =end class TagSetPresenter < Presenter - def initialize(source) - @category_cache = {} + def initialize(tags) + @tags = tags + fetch_categories end - def to_list_html(template, options = {}) - ul_class_attribute = options[:ul_class] ? %{class="#{options[:ul_class]}"} : "" - ul_id_attribute = options[:ul_id] ? %{id="#{options[:ul_id]}"} : "" - + def tag_list_html(template, options = {}) html = "" - html << "
<%= submit_tag "Post comment", :class => "expand-comment-response" %>
+ + + + <% form_tag(comments_path) do %> + <%= hidden_field "comment", "post_id", :value => post.id%> + <%= text_area "comment", "body", :size => "60x7" %>+ <%= submit_tag "Post" %> + <%= submit_tag "Preview" %> + <% end %> +