Merge branch 'master' into glitch-soc/merge-upstream

Conflicts:
- `app/controllers/api/v1/statuses_controller.rb`:
  Conflict due to upstream adding a new parameter (with_rate_limit),
  too close to glitch-soc's own additional parameter (content_type).
  Added upstream's parameter.
- `app/services/post_status_service.rb`:
  Conflict due to upstream adding a new parameter (rate_limit),
  too close to glitch-soc's own additional parameter (content_type).
  Added upstream's parameter.
- `app/views/settings/preferences/appearance/show.html.haml`:
  Conflict due to us not exposing theme settings here (as we have
  a different flavour/skin menu).
  Took upstream change, while still not exposing theme settings.
- `config/webpack/shared.js`:
  Coding style fixes for a part we have rewritten.
  Discarded upstream changes.
This commit is contained in:
Thibaut Girka
2020-03-08 19:38:53 +01:00
138 changed files with 573 additions and 317 deletions

View File

@@ -106,6 +106,7 @@ class Account < ApplicationRecord
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).left_outer_joins(:account_stat) }
scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) }
scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc, accounts.id desc')) }
scope :by_recent_sign_in, -> { order(Arel.sql('(case when users.current_sign_in_at is null then 1 else 0 end) asc, users.current_sign_in_at desc, accounts.id desc')) }
scope :popular, -> { order('account_stats.followers_count desc') }
scope :by_domain_and_subdomains, ->(domain) { where(domain: domain).or(where(arel_table[:domain].matches('%.' + domain))) }
scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) }

View File

@@ -14,6 +14,7 @@ class AccountFilter
email
ip
staff
order
).freeze
attr_reader :params
@@ -24,7 +25,7 @@ class AccountFilter
end
def results
scope = Account.recent.includes(:user)
scope = Account.includes(:user).reorder(nil)
params.each do |key, value|
scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
@@ -38,6 +39,7 @@ class AccountFilter
def set_defaults!
params['local'] = '1' if params['remote'].blank?
params['active'] = '1' if params['suspended'].blank? && params['silenced'].blank? && params['pending'].blank?
params['order'] = 'recent' if params['order'].blank?
end
def scope_for(key, value)
@@ -51,9 +53,9 @@ class AccountFilter
when 'active'
Account.without_suspended
when 'pending'
accounts_with_users.merge User.pending
accounts_with_users.merge(User.pending)
when 'disabled'
accounts_with_users.merge User.disabled
accounts_with_users.merge(User.disabled)
when 'silenced'
Account.silenced
when 'suspended'
@@ -63,16 +65,31 @@ class AccountFilter
when 'display_name'
Account.matches_display_name(value)
when 'email'
accounts_with_users.merge User.matches_email(value)
accounts_with_users.merge(User.matches_email(value))
when 'ip'
valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value)) : Account.none
when 'staff'
accounts_with_users.merge User.staff
accounts_with_users.merge(User.staff)
when 'order'
order_scope(value)
else
raise "Unknown filter: #{key}"
end
end
def order_scope(value)
case value
when 'active'
params['remote'] ? Account.joins(:account_stat).by_recent_status : Account.joins(:user).by_recent_sign_in
when 'recent'
Account.recent
when 'alphabetic'
Account.alphabetic
else
raise "Unknown order: #{value}"
end
end
def accounts_with_users
Account.joins(:user)
end

View File

@@ -48,6 +48,10 @@ class Announcement < ApplicationRecord
@mentions ||= Account.from_text(text)
end
def statuses
@statuses ||= Status.from_text(text)
end
def tags
@tags ||= Tag.find_or_create_by_names(Extractor.extract_hashtags(text))
end

View File

@@ -87,10 +87,10 @@ module AccountInteractions
has_many :announcement_mutes, dependent: :destroy
end
def follow!(other_account, reblogs: nil, uri: nil)
def follow!(other_account, reblogs: nil, uri: nil, rate_limit: false)
reblogs = true if reblogs.nil?
rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri)
rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri, rate_limit: rate_limit)
.find_or_create_by!(target_account: other_account)
rel.update!(show_reblogs: reblogs)
@@ -99,6 +99,18 @@ module AccountInteractions
rel
end
def request_follow!(other_account, reblogs: nil, uri: nil, rate_limit: false)
reblogs = true if reblogs.nil?
rel = follow_requests.create_with(show_reblogs: reblogs, uri: uri, rate_limit: rate_limit)
.find_or_create_by!(target_account: other_account)
rel.update!(show_reblogs: reblogs)
remove_potential_friendship(other_account)
rel
end
def block!(other_account, uri: nil)
remove_potential_friendship(other_account)
block_relationships.create_with(uri: uri)

View File

@@ -0,0 +1,36 @@
# frozen_string_literal: true
module RateLimitable
extend ActiveSupport::Concern
def rate_limit=(value)
@rate_limit = value
end
def rate_limit?
@rate_limit
end
def rate_limiter(by, options = {})
return @rate_limiter if defined?(@rate_limiter)
@rate_limiter = RateLimiter.new(by, options)
end
class_methods do
def rate_limit(options = {})
after_create do
by = public_send(options[:by])
if rate_limit? && by&.local?
rate_limiter(by, options).record!
@rate_limit_recorded = true
end
end
after_rollback do
rate_limiter(public_send(options[:by]), options).rollback! if @rate_limit_recorded
end
end
end
end

View File

@@ -15,6 +15,9 @@
class Follow < ApplicationRecord
include Paginable
include RelationshipCacheable
include RateLimitable
rate_limit by: :account, family: :follows
belongs_to :account
belongs_to :target_account, class_name: 'Account'

View File

@@ -15,6 +15,9 @@
class FollowRequest < ApplicationRecord
include Paginable
include RelationshipCacheable
include RateLimitable
rate_limit by: :account, family: :follows
belongs_to :account
belongs_to :target_account, class_name: 'Account'

View File

@@ -170,6 +170,7 @@ class MediaAttachment < ApplicationRecord
def variant?(other_file_name)
return true if file_file_name == other_file_name
return false if file_file_name.nil?
formats = file.styles.values.map(&:format).compact

View File

@@ -35,6 +35,9 @@ class Status < ApplicationRecord
include Paginable
include Cacheable
include StatusThreadingConcern
include RateLimitable
rate_limit by: :account, family: :statuses
self.discard_column = :deleted_at
@@ -416,6 +419,21 @@ class Status < ApplicationRecord
end
end
def from_text(text)
return [] if text.blank?
text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.map do |url|
status = begin
if TagManager.instance.local_url?(url)
ActivityPub::TagManager.instance.uri_to_resource(url, Status)
else
Status.find_by(uri: url) || Status.find_by(url: url)
end
end
status&.distributable? ? status : nil
end.compact
end
private
def timeline_scope(local_only = false)