Merge upstream 2.0ish #165
This commit is contained in:
@@ -92,6 +92,10 @@ class Account < ApplicationRecord
|
||||
has_many :reports
|
||||
has_many :targeted_reports, class_name: 'Report', foreign_key: :target_account_id
|
||||
|
||||
# Moderation notes
|
||||
has_many :account_moderation_notes, dependent: :destroy
|
||||
has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy
|
||||
|
||||
scope :remote, -> { where.not(domain: nil) }
|
||||
scope :local, -> { where(domain: nil) }
|
||||
scope :without_followers, -> { where(followers_count: 0) }
|
||||
@@ -139,6 +143,15 @@ class Account < ApplicationRecord
|
||||
subscription_expires_at.present?
|
||||
end
|
||||
|
||||
def possibly_stale?
|
||||
last_webfingered_at.nil? || last_webfingered_at <= 1.day.ago
|
||||
end
|
||||
|
||||
def refresh!
|
||||
return if local?
|
||||
ResolveRemoteAccountService.new.call(acct)
|
||||
end
|
||||
|
||||
def keypair
|
||||
@keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key)
|
||||
end
|
||||
@@ -183,7 +196,8 @@ class Account < ApplicationRecord
|
||||
end
|
||||
|
||||
def inboxes
|
||||
reorder(nil).where(protocol: :activitypub).pluck("distinct coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url)")
|
||||
urls = reorder(nil).where(protocol: :activitypub).pluck("distinct coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url)")
|
||||
DeliveryFailureTracker.filter(urls)
|
||||
end
|
||||
|
||||
def triadic_closures(account, limit: 5, offset: 0)
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: account_domain_blocks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer
|
||||
# domain :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class AccountDomainBlock < ApplicationRecord
|
||||
|
@@ -9,9 +9,11 @@ class AccountFilter
|
||||
|
||||
def results
|
||||
scope = Account.alphabetic
|
||||
|
||||
params.each do |key, value|
|
||||
scope.merge!(scope_for(key, value)) if value.present?
|
||||
end
|
||||
|
||||
scope
|
||||
end
|
||||
|
||||
|
21
app/models/account_moderation_note.rb
Normal file
21
app/models/account_moderation_note.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: account_moderation_notes
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# content :text not null
|
||||
# account_id :integer not null
|
||||
# target_account_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class AccountModerationNote < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :target_account, class_name: 'Account'
|
||||
|
||||
scope :latest, -> { reorder('created_at DESC') }
|
||||
|
||||
validates :content, presence: true, length: { maximum: 500 }
|
||||
end
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: blocks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# target_account_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
# target_account_id :integer not null
|
||||
#
|
||||
|
||||
class Block < ApplicationRecord
|
||||
|
@@ -3,9 +3,9 @@
|
||||
#
|
||||
# Table name: conversation_mutes
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# conversation_id :integer not null
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class ConversationMute < ApplicationRecord
|
||||
|
@@ -12,6 +12,9 @@
|
||||
# image_updated_at :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# disabled :boolean default(FALSE), not null
|
||||
# uri :string
|
||||
# image_remote_url :string
|
||||
#
|
||||
|
||||
class CustomEmoji < ApplicationRecord
|
||||
@@ -21,15 +24,25 @@ class CustomEmoji < ApplicationRecord
|
||||
:(#{SHORTCODE_RE_FRAGMENT}):
|
||||
(?=[^[:alnum:]:]|$)/x
|
||||
|
||||
has_attached_file :image
|
||||
has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce -strip' } }
|
||||
|
||||
validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { in: 0..50.kilobytes }
|
||||
validates :shortcode, uniqueness: { scope: :domain }, format: { with: /\A#{SHORTCODE_RE_FRAGMENT}\z/ }, length: { minimum: 2 }
|
||||
|
||||
scope :local, -> { where(domain: nil) }
|
||||
scope :local, -> { where(domain: nil) }
|
||||
scope :remote, -> { where.not(domain: nil) }
|
||||
scope :alphabetic, -> { order(domain: :asc, shortcode: :asc) }
|
||||
|
||||
include Remotable
|
||||
|
||||
def local?
|
||||
domain.nil?
|
||||
end
|
||||
|
||||
def object_type
|
||||
:emoji
|
||||
end
|
||||
|
||||
class << self
|
||||
def from_text(text, domain)
|
||||
return [] if text.blank?
|
||||
@@ -38,7 +51,7 @@ class CustomEmoji < ApplicationRecord
|
||||
|
||||
return [] if shortcodes.empty?
|
||||
|
||||
where(shortcode: shortcodes, domain: domain)
|
||||
where(shortcode: shortcodes, domain: domain, disabled: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
34
app/models/custom_emoji_filter.rb
Normal file
34
app/models/custom_emoji_filter.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CustomEmojiFilter
|
||||
attr_reader :params
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def results
|
||||
scope = CustomEmoji.alphabetic
|
||||
|
||||
params.each do |key, value|
|
||||
scope.merge!(scope_for(key, value)) if value.present?
|
||||
end
|
||||
|
||||
scope
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scope_for(key, value)
|
||||
case key.to_s
|
||||
when 'local'
|
||||
CustomEmoji.local
|
||||
when 'remote'
|
||||
CustomEmoji.remote
|
||||
when 'by_domain'
|
||||
CustomEmoji.where(domain: value)
|
||||
else
|
||||
raise "Unknown filter: #{key}"
|
||||
end
|
||||
end
|
||||
end
|
@@ -3,12 +3,12 @@
|
||||
#
|
||||
# Table name: domain_blocks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# domain :string default(""), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# severity :integer default("silence")
|
||||
# reject_media :boolean default(FALSE), not null
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class DomainBlock < ApplicationRecord
|
||||
|
17
app/models/email_domain_block.rb
Normal file
17
app/models/email_domain_block.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: email_domain_blocks
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# domain :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class EmailDomainBlock < ApplicationRecord
|
||||
def self.block?(email)
|
||||
domain = email.gsub(/.+@([^.]+)/, '\1')
|
||||
where(domain: domain).exists?
|
||||
end
|
||||
end
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: favourites
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# status_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
# status_id :integer not null
|
||||
#
|
||||
|
||||
class Favourite < ApplicationRecord
|
||||
|
@@ -19,7 +19,7 @@ class Feed
|
||||
def from_redis(limit, max_id, since_id)
|
||||
max_id = '+inf' if max_id.blank?
|
||||
since_id = '-inf' if since_id.blank?
|
||||
unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", "(#{since_id}", limit: [0, limit], with_scores: true).map(&:last).map(&:to_i)
|
||||
unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", "(#{since_id}", limit: [0, limit], with_scores: true).map(&:first).map(&:to_i)
|
||||
Status.where(id: unhydrated).cache_ids
|
||||
end
|
||||
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: follows
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# target_account_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
# target_account_id :integer not null
|
||||
#
|
||||
|
||||
class Follow < ApplicationRecord
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: follow_requests
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# target_account_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
# target_account_id :integer not null
|
||||
#
|
||||
|
||||
class FollowRequest < ApplicationRecord
|
||||
|
@@ -3,8 +3,6 @@
|
||||
#
|
||||
# Table name: imports
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# type :integer not null
|
||||
# approved :boolean default(FALSE), not null
|
||||
# created_at :datetime not null
|
||||
@@ -13,6 +11,8 @@
|
||||
# data_content_type :string
|
||||
# data_file_size :integer
|
||||
# data_updated_at :datetime
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class Import < ApplicationRecord
|
||||
|
@@ -16,6 +16,7 @@
|
||||
# shortcode :string
|
||||
# type :integer default("image"), not null
|
||||
# file_meta :json
|
||||
# description :text
|
||||
#
|
||||
|
||||
require 'mime/types'
|
||||
@@ -75,6 +76,7 @@ class MediaAttachment < ApplicationRecord
|
||||
validates_attachment_size :file, less_than: 8.megabytes
|
||||
|
||||
validates :account, presence: true
|
||||
validates :description, length: { maximum: 420 }, if: :local?
|
||||
|
||||
scope :attached, -> { where.not(status_id: nil) }
|
||||
scope :unattached, -> { where(status_id: nil) }
|
||||
@@ -95,6 +97,7 @@ class MediaAttachment < ApplicationRecord
|
||||
shortcode
|
||||
end
|
||||
|
||||
before_create :prepare_description, unless: :local?
|
||||
before_create :set_shortcode
|
||||
before_post_process :set_type_and_extension
|
||||
before_save :set_meta
|
||||
@@ -157,6 +160,10 @@ class MediaAttachment < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def prepare_description
|
||||
self.description = description.strip[0...420] unless description.nil?
|
||||
end
|
||||
|
||||
def set_type_and_extension
|
||||
self.type = VIDEO_MIME_TYPES.include?(file_content_type) ? :video : AUDIO_MIME_TYPES.include?(file_content_type) ? :audio : :image
|
||||
extension = AUDIO_MIME_TYPES.include?(file_content_type) ? '.mp4' : appropriate_extension
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: mentions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer
|
||||
# status_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class Mention < ApplicationRecord
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: mutes
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# target_account_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
# target_account_id :integer not null
|
||||
# hide_notifications :boolean default(TRUE), not null
|
||||
#
|
||||
|
||||
|
@@ -3,15 +3,15 @@
|
||||
#
|
||||
# Table name: reports
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer not null
|
||||
# target_account_id :integer not null
|
||||
# status_ids :integer default([]), not null, is an Array
|
||||
# comment :text default(""), not null
|
||||
# action_taken :boolean default(FALSE), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :integer not null
|
||||
# action_taken_by_account_id :integer
|
||||
# id :integer not null, primary key
|
||||
# target_account_id :integer not null
|
||||
#
|
||||
|
||||
class Report < ApplicationRecord
|
||||
|
@@ -3,13 +3,13 @@
|
||||
#
|
||||
# Table name: settings
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# var :string not null
|
||||
# value :text
|
||||
# thing_type :string
|
||||
# thing_id :integer
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
# id :integer not null, primary key
|
||||
# thing_id :integer
|
||||
#
|
||||
|
||||
class Setting < RailsSettings::Base
|
||||
|
@@ -136,6 +136,8 @@ class Status < ApplicationRecord
|
||||
|
||||
after_create :store_uri, if: :local?
|
||||
|
||||
around_create Mastodon::Snowflake::Callbacks
|
||||
|
||||
before_validation :prepare_contents, if: :local?
|
||||
before_validation :set_reblog
|
||||
before_validation :set_visibility
|
||||
|
@@ -1,16 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: stream_entries
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer
|
||||
# activity_id :integer
|
||||
# activity_type :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# hidden :boolean default(FALSE), not null
|
||||
# account_id :integer
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class StreamEntry < ApplicationRecord
|
||||
|
@@ -3,16 +3,16 @@
|
||||
#
|
||||
# Table name: subscriptions
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# callback_url :string default(""), not null
|
||||
# secret :string
|
||||
# expires_at :datetime
|
||||
# confirmed :boolean default(FALSE), not null
|
||||
# account_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# last_successful_delivery_at :datetime
|
||||
# domain :string
|
||||
# account_id :integer not null
|
||||
# id :integer not null, primary key
|
||||
#
|
||||
|
||||
class Subscription < ApplicationRecord
|
||||
|
@@ -3,11 +3,11 @@
|
||||
#
|
||||
# Table name: web_settings
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# data :json
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
#
|
||||
|
||||
class Web::Setting < ApplicationRecord
|
||||
|
Reference in New Issue
Block a user