Merge remote-tracking branch 'glitchsoc/master' into 454-allow-keyword-mutes-to-skip-mentions

Conflicts:
 	app/models/glitch/keyword_mute.rb
This commit is contained in:
David Yip
2018-06-12 16:39:30 -05:00
100 changed files with 477 additions and 486 deletions

View File

@@ -24,14 +24,17 @@ module Remotable
Request.new(:get, url).perform do |response|
next if response.code != 200
matches = response.headers['content-disposition']&.match(/filename="([^"]*)"/)
filename = matches.nil? ? parsed_url.path.split('/').last : matches[1]
content_type = parse_content_type(response.headers.get('content-type').last)
extname = detect_extname_from_content_type(content_type)
if extname.nil?
disposition = response.headers.get('content-disposition').last
matches = disposition&.match(/filename="([^"]*)"/)
filename = matches.nil? ? parsed_url.path.split('/').last : matches[1]
extname = filename.nil? ? '' : File.extname(filename)
end
basename = SecureRandom.hex(8)
extname = if filename.nil?
''
else
File.extname(filename)
end
send("#{attachment_name}=", StringIO.new(response.body_with_limit(limit)))
send("#{attachment_name}_file_name=", basename + extname)
@@ -57,4 +60,26 @@ module Remotable
end
end
end
private
def detect_extname_from_content_type(content_type)
return if content_type.nil?
type = MIME::Types[content_type].first
return if type.nil?
extname = type.extensions.first
return if extname.nil?
".#{extname}"
end
def parse_content_type(content_type)
return if content_type.nil?
content_type.split(/\s*;\s*/).first
end
end

View File

@@ -51,12 +51,16 @@ module StatusThreadingConcern
end
def descendant_statuses(limit, max_child_id, since_child_id, depth)
Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth])
# use limit + 1 and depth + 1 because 'self' is included
depth += 1 if depth.present?
limit += 1 if limit.present?
descendants_with_self = Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth])
WITH RECURSIVE search_tree(id, path)
AS (
SELECT id, ARRAY[id]
FROM statuses
WHERE in_reply_to_id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE)
WHERE id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE)
UNION ALL
SELECT statuses.id, path || statuses.id
FROM search_tree
@@ -68,6 +72,8 @@ module StatusThreadingConcern
ORDER BY path
LIMIT :limit
SQL
descendants_with_self - [self]
end
def find_statuses_from_tree_path(ids, account)

View File

@@ -67,7 +67,7 @@ class Glitch::KeywordMute < ApplicationRecord
def matches?(str, required_scope)
((required_scope & scope) == required_scope) && \
str =~ (whole_word ? boundary_regex_for_keyword : /#{keyword}/i)
str =~ (whole_word ? boundary_regex_for_keyword : /#{Regexp.escape(keyword)}/i)
end
end

View File

@@ -55,7 +55,7 @@ class Status < ApplicationRecord
has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy
has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread
has_many :mentions, dependent: :destroy
has_many :media_attachments, dependent: :destroy
has_many :media_attachments, dependent: :nullify
has_and_belongs_to_many :tags
has_and_belongs_to_many :preview_cards
@@ -194,7 +194,6 @@ class Status < ApplicationRecord
before_validation :set_reblog
before_validation :set_visibility
before_validation :set_conversation
before_validation :set_sensitivity
before_validation :set_local
class << self
@@ -317,7 +316,11 @@ class Status < ApplicationRecord
# non-followers can see everything that isn't private/direct, but can see stuff they are mentioned in.
visibility.push(:private) if account.following?(target_account)
where(visibility: visibility).or(where(id: account.mentions.select(:status_id)))
scope = left_outer_joins(:reblog)
scope.where(visibility: visibility)
.or(scope.where(id: account.mentions.select(:status_id)))
.merge(scope.where(reblog_of_id: nil).or(scope.where.not(reblogs_statuses: { account_id: account.excluded_from_timeline_account_ids })))
end
end
@@ -388,10 +391,6 @@ class Status < ApplicationRecord
self.sensitive = false if sensitive.nil?
end
def set_sensitivity
self.sensitive = sensitive || spoiler_text.present?
end
def set_locality
if account.domain.nil? && !attribute_changed?(:local_only)
self.local_only = marked_local_only?

View File

@@ -1,9 +1,7 @@
# frozen_string_literal: true
class TrendingTags
KEY = 'trending_tags'
EXPIRE_HISTORY_AFTER = 7.days.seconds
THRESHOLD = 5
class << self
def record_use!(tag, account, at_time = Time.now.utc)
@@ -11,30 +9,10 @@ class TrendingTags
increment_historical_use!(tag.id, at_time)
increment_unique_use!(tag.id, account.id, at_time)
increment_vote!(tag.id, at_time)
end
def get(limit)
tag_ids = redis.zrevrange(KEY, 0, limit).map(&:to_i)
tags = Tag.where(id: tag_ids).to_a.map { |tag| [tag.id, tag] }.to_h
tag_ids.map { |tag_id| tags[tag_id] }.compact
end
private
def increment_vote!(tag_id, at_time)
expected = redis.pfcount("activity:tags:#{tag_id}:#{(at_time - 1.day).beginning_of_day.to_i}:accounts").to_f
expected = 1.0 if expected.zero?
observed = redis.pfcount("activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}:accounts").to_f
if expected > observed || observed < THRESHOLD
redis.zrem(KEY, tag_id.to_s)
else
score = ((observed - expected)**2) / expected
redis.zadd(KEY, score, tag_id.to_s)
end
end
def increment_historical_use!(tag_id, at_time)
key = "activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}"
redis.incrby(key, 1)