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:
@@ -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) }
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
36
app/models/concerns/rate_limitable.rb
Normal file
36
app/models/concerns/rate_limitable.rb
Normal 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
|
@@ -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'
|
||||
|
@@ -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'
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user