mirror of
https://framagit.org/tykayn/mastodon.git
synced 2023-08-25 08:33:12 +02:00
Merge remote-tracking branch 'gh/master'
This commit is contained in:
commit
ab8e381e3c
@ -27,10 +27,10 @@ plugins:
|
||||
enabled: true
|
||||
eslint:
|
||||
enabled: true
|
||||
channel: eslint-5
|
||||
channel: eslint-6
|
||||
rubocop:
|
||||
enabled: true
|
||||
channel: rubocop-0-71
|
||||
channel: rubocop-0-76
|
||||
sass-lint:
|
||||
enabled: true
|
||||
exclude_patterns:
|
||||
|
@ -71,6 +71,9 @@ Naming/MemoizedInstanceVariableName:
|
||||
Rails:
|
||||
Enabled: true
|
||||
|
||||
Rails/EnumHash:
|
||||
Enabled: false
|
||||
|
||||
Rails/HasAndBelongsToMany:
|
||||
Enabled: false
|
||||
|
||||
@ -102,6 +105,9 @@ Style/Documentation:
|
||||
Style/DoubleNegation:
|
||||
Enabled: true
|
||||
|
||||
Style/FormatStringToken:
|
||||
Enabled: false
|
||||
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: true
|
||||
|
||||
|
4
Gemfile
4
Gemfile
@ -5,7 +5,7 @@ ruby '>= 2.4.0', '< 2.7.0'
|
||||
|
||||
gem 'pkg-config', '~> 1.4'
|
||||
|
||||
gem 'puma', '~> 4.2'
|
||||
gem 'puma', '~> 4.3'
|
||||
gem 'rails', '~> 5.2.3'
|
||||
gem 'thor', '~> 0.20'
|
||||
|
||||
@ -116,7 +116,7 @@ end
|
||||
group :test do
|
||||
gem 'capybara', '~> 3.29'
|
||||
gem 'climate_control', '~> 0.2'
|
||||
gem 'faker', '~> 2.7'
|
||||
gem 'faker', '~> 2.8'
|
||||
gem 'microformats', '~> 4.1'
|
||||
gem 'rails-controller-testing', '~> 1.0'
|
||||
gem 'rspec-sidekiq', '~> 3.0'
|
||||
|
12
Gemfile.lock
12
Gemfile.lock
@ -132,7 +132,7 @@ GEM
|
||||
ffi (~> 1.10.0)
|
||||
bootsnap (1.4.5)
|
||||
msgpack (~> 1.0)
|
||||
brakeman (4.7.1)
|
||||
brakeman (4.7.2)
|
||||
browser (2.7.1)
|
||||
builder (3.2.3)
|
||||
bullet (6.0.2)
|
||||
@ -240,7 +240,7 @@ GEM
|
||||
tzinfo
|
||||
excon (0.62.0)
|
||||
fabrication (2.21.0)
|
||||
faker (2.7.0)
|
||||
faker (2.8.0)
|
||||
i18n (>= 1.6, < 1.8)
|
||||
faraday (0.15.4)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
@ -387,7 +387,7 @@ GEM
|
||||
net-scp (2.0.0)
|
||||
net-ssh (>= 2.6.5, < 6.0.0)
|
||||
net-ssh (5.2.0)
|
||||
nio4r (2.5.1)
|
||||
nio4r (2.5.2)
|
||||
nokogiri (1.10.5)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
nokogumbo (2.0.1)
|
||||
@ -453,7 +453,7 @@ GEM
|
||||
pry-rails (0.3.9)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (4.0.1)
|
||||
puma (4.2.0)
|
||||
puma (4.3.1)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
@ -710,7 +710,7 @@ DEPENDENCIES
|
||||
doorkeeper (~> 5.2)
|
||||
dotenv-rails (~> 2.7)
|
||||
fabrication (~> 2.21)
|
||||
faker (~> 2.7)
|
||||
faker (~> 2.8)
|
||||
fast_blank (~> 1.0)
|
||||
fastimage
|
||||
fog-core (<= 2.1.0)
|
||||
@ -763,7 +763,7 @@ DEPENDENCIES
|
||||
private_address_check (~> 0.5)
|
||||
pry-byebug (~> 3.7)
|
||||
pry-rails (~> 0.3)
|
||||
puma (~> 4.2)
|
||||
puma (~> 4.3)
|
||||
pundit (~> 2.1)
|
||||
rack-attack (~> 6.2)
|
||||
rack-cors (~> 1.1)
|
||||
|
@ -20,6 +20,10 @@ class Api::BaseController < ApplicationController
|
||||
render json: { error: e.to_s }, status: 422
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotUnique do
|
||||
render json: { error: 'Duplicate record' }, status: 422
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
render json: { error: 'Record not found' }, status: 404
|
||||
end
|
||||
|
@ -136,6 +136,6 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def respond_with_error(code)
|
||||
render "errors/#{code}", layout: 'error', status: code
|
||||
render "errors/#{code}", layout: 'error', status: code, formats: [:html]
|
||||
end
|
||||
end
|
||||
|
@ -62,6 +62,8 @@ module AccountsHelper
|
||||
def account_badge(account, all: false)
|
||||
if account.bot?
|
||||
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
|
||||
elsif account.group?
|
||||
content_tag(:div, content_tag(:div, t('accounts.roles.group'), class: 'account-role group'), class: 'roles')
|
||||
elsif (Setting.show_staff_badge && account.user_staff?) || all
|
||||
content_tag(:div, class: 'roles') do
|
||||
if all && !account.user_staff?
|
||||
|
@ -67,9 +67,7 @@ class Poll extends ImmutablePureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
handleOptionChange = e => {
|
||||
const { target: { value } } = e;
|
||||
|
||||
_toggleOption = value => {
|
||||
if (this.props.poll.get('multiple')) {
|
||||
const tmp = { ...this.state.selected };
|
||||
if (tmp[value]) {
|
||||
@ -83,8 +81,20 @@ class Poll extends ImmutablePureComponent {
|
||||
tmp[value] = true;
|
||||
this.setState({ selected: tmp });
|
||||
}
|
||||
}
|
||||
|
||||
handleOptionChange = ({ target: { value } }) => {
|
||||
this._toggleOption(value);
|
||||
};
|
||||
|
||||
handleOptionKeyPress = (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
this._toggleOption(e.target.getAttribute('data-index'));
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
handleVote = () => {
|
||||
if (this.props.disabled) {
|
||||
return;
|
||||
@ -135,7 +145,17 @@ class Poll extends ImmutablePureComponent {
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
{!showResults && <span className={classNames('poll__input', { checkbox: poll.get('multiple'), active })} />}
|
||||
{!showResults && (
|
||||
<span
|
||||
className={classNames('poll__input', { checkbox: poll.get('multiple'), active })}
|
||||
tabIndex='0'
|
||||
role={poll.get('multiple') ? 'checkbox' : 'radio'}
|
||||
onKeyPress={this.handleOptionKeyPress}
|
||||
aria-checked={active}
|
||||
aria-label={option.get('title')}
|
||||
data-index={optionIndex}
|
||||
/>
|
||||
)}
|
||||
{showResults && <span className='poll__number'>
|
||||
{!!voted && <Icon id='check' className='poll__vote__mark' title={intl.formatMessage(messages.voted)} />}
|
||||
{Math.round(percent)}%
|
||||
|
@ -215,7 +215,8 @@ class Status extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
handleHotkeyOpenMedia = e => {
|
||||
const { status, onOpenMedia, onOpenVideo } = this.props;
|
||||
const { onOpenMedia, onOpenVideo } = this.props;
|
||||
const status = this._properStatus();
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -173,9 +173,9 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
const account = status.get('account');
|
||||
|
||||
if (relationship && relationship.get('blocking')) {
|
||||
onBlock(status);
|
||||
} else {
|
||||
onUnblock(account);
|
||||
} else {
|
||||
onBlock(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,9 +238,18 @@ class Header extends ImmutablePureComponent {
|
||||
const content = { __html: account.get('note_emojified') };
|
||||
const displayNameHtml = { __html: account.get('display_name_html') };
|
||||
const fields = account.get('fields');
|
||||
const badge = account.get('bot') ? (<div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div>) : null;
|
||||
const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct');
|
||||
|
||||
let badge;
|
||||
|
||||
if (account.get('bot')) {
|
||||
badge = (<div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div>);
|
||||
} else if (account.get('group')) {
|
||||
badge = (<div className='account-role group'><FormattedMessage id='account.badges.group' defaultMessage='Group' /></div>);
|
||||
} else {
|
||||
badge = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames('account__header', { inactive: !!account.get('moved') })} ref={this.setRef}>
|
||||
<div className='account__header__image'>
|
||||
|
@ -13,6 +13,8 @@ const messages = defineMessages({
|
||||
add_option: { id: 'compose_form.poll.add_option', defaultMessage: 'Add a choice' },
|
||||
remove_option: { id: 'compose_form.poll.remove_option', defaultMessage: 'Remove this choice' },
|
||||
poll_duration: { id: 'compose_form.poll.duration', defaultMessage: 'Poll duration' },
|
||||
switchToMultiple: { id: 'compose_form.poll.switch_to_multiple', defaultMessage: 'Change poll to allow multiple choices' },
|
||||
switchToSingle: { id: 'compose_form.poll.switch_to_single', defaultMessage: 'Change poll to allow for a single choice' },
|
||||
minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' },
|
||||
hours: { id: 'intervals.full.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}}' },
|
||||
days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
|
||||
@ -50,6 +52,12 @@ class Option extends React.PureComponent {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
handleCheckboxKeypress = e => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
this.handleToggleMultiple(e);
|
||||
}
|
||||
}
|
||||
|
||||
onSuggestionsClearRequested = () => {
|
||||
this.props.onClearSuggestions();
|
||||
}
|
||||
@ -71,8 +79,11 @@ class Option extends React.PureComponent {
|
||||
<span
|
||||
className={classNames('poll__input', { checkbox: isPollMultiple })}
|
||||
onClick={this.handleToggleMultiple}
|
||||
onKeyPress={this.handleCheckboxKeypress}
|
||||
role='button'
|
||||
tabIndex='0'
|
||||
title={intl.formatMessage(isPollMultiple ? messages.switchToMultiple : messages.switchToSingle)}
|
||||
aria-label={intl.formatMessage(isPollMultiple ? messages.switchToMultiple : messages.switchToSingle)}
|
||||
/>
|
||||
|
||||
<AutosuggestInput
|
||||
|
@ -120,9 +120,9 @@ class ActionBar extends React.PureComponent {
|
||||
const account = status.get('account');
|
||||
|
||||
if (relationship && relationship.get('blocking')) {
|
||||
onBlock(status);
|
||||
} else {
|
||||
onUnblock(account);
|
||||
} else {
|
||||
onBlock(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ class Status extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
handleHotkeyOpenMedia = e => {
|
||||
const { status } = this.props;
|
||||
const status = this._properStatus();
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import WebSocketClient from 'websocket.js';
|
||||
import WebSocketClient from '@gamestdio/websocket';
|
||||
|
||||
const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max));
|
||||
|
||||
|
@ -91,6 +91,23 @@
|
||||
border-color: $valid-value-color;
|
||||
background: $valid-value-color;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
border-width: 4px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
outline: 0 !important;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__number {
|
||||
@ -160,6 +177,10 @@
|
||||
button,
|
||||
select {
|
||||
flex: 1 1 50%;
|
||||
|
||||
&:focus {
|
||||
border-color: $highlight-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ class ActivityPub::Activity
|
||||
def distribute(status)
|
||||
crawl_links(status)
|
||||
|
||||
notify_about_reblog(status) if reblog_of_local_account?(status)
|
||||
notify_about_reblog(status) if reblog_of_local_account?(status) && !reblog_by_following_group_account?(status)
|
||||
notify_about_mentions(status)
|
||||
|
||||
# Only continue if the status is supposed to have arrived in real-time.
|
||||
@ -105,6 +105,10 @@ class ActivityPub::Activity
|
||||
status.reblog? && status.reblog.account.local?
|
||||
end
|
||||
|
||||
def reblog_by_following_group_account?(status)
|
||||
status.reblog? && status.account.group? && status.reblog.account.following?(status.account)
|
||||
end
|
||||
|
||||
def notify_about_reblog(status)
|
||||
NotifyService.new.call(status.reblog.account, status)
|
||||
end
|
||||
|
@ -35,6 +35,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
|
||||
def serializable_hash(options = nil)
|
||||
named_contexts = {}
|
||||
context_extensions = {}
|
||||
|
||||
options = serialization_options(options)
|
||||
serialized_hash = serializer.serializable_hash(options.merge(named_contexts: named_contexts, context_extensions: context_extensions))
|
||||
serialized_hash = serialized_hash.select { |k, _| options[:fields].include?(k) } if options[:fields]
|
||||
|
@ -68,10 +68,19 @@ class ActivityPub::TagManager
|
||||
if status.account.silenced?
|
||||
# Only notify followers if the account is locally silenced
|
||||
account_ids = status.active_mentions.pluck(:account_id)
|
||||
to = status.account.followers.where(id: account_ids).map { |account| uri_for(account) }
|
||||
to.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).map { |request| uri_for(request.account) })
|
||||
to = status.account.followers.where(id: account_ids).each_with_object([]) do |account, result|
|
||||
result << uri_for(account)
|
||||
result << account.followers_url if account.group?
|
||||
end
|
||||
to.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).each_with_object([]) do |request, result|
|
||||
result << uri_for(request.account)
|
||||
result << request.account.followers_url if request.account.group?
|
||||
end)
|
||||
else
|
||||
status.active_mentions.map { |mention| uri_for(mention.account) }
|
||||
status.active_mentions.each_with_object([]) do |mention, result|
|
||||
result << uri_for(mention.account)
|
||||
result << mention.account.followers_url if mention.account.group?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -97,10 +106,19 @@ class ActivityPub::TagManager
|
||||
if status.account.silenced?
|
||||
# Only notify followers if the account is locally silenced
|
||||
account_ids = status.active_mentions.pluck(:account_id)
|
||||
cc.concat(status.account.followers.where(id: account_ids).map { |account| uri_for(account) })
|
||||
cc.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).map { |request| uri_for(request.account) })
|
||||
cc.concat(status.account.followers.where(id: account_ids).each_with_object([]) do |account, result|
|
||||
result << uri_for(account)
|
||||
result << account.followers_url if account.group?
|
||||
end)
|
||||
cc.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).each_with_object([]) do |request, result|
|
||||
result << uri_for(request.account)
|
||||
result << request.account.followers_url if request.account.group?
|
||||
end)
|
||||
else
|
||||
cc.concat(status.active_mentions.map { |mention| uri_for(mention.account) })
|
||||
cc.concat(status.active_mentions.each_with_object([]) do |mention, result|
|
||||
result << uri_for(mention.account)
|
||||
result << mention.account.followers_url if mention.account.group?
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -44,7 +44,7 @@ class LanguageDetector
|
||||
words = text.scan(RELIABLE_CHARACTERS_RE)
|
||||
|
||||
if words.present?
|
||||
words.reduce(0) { |acc, elem| acc + elem.size }.to_f / text.size.to_f > 0.3
|
||||
words.reduce(0) { |acc, elem| acc + elem.size }.to_f / text.size > 0.3
|
||||
else
|
||||
false
|
||||
end
|
||||
|
@ -93,6 +93,7 @@ class Account < ApplicationRecord
|
||||
scope :without_silenced, -> { where(silenced_at: nil) }
|
||||
scope :recent, -> { reorder(id: :desc) }
|
||||
scope :bots, -> { where(actor_type: %w(Application Service)) }
|
||||
scope :groups, -> { where(actor_type: 'Group') }
|
||||
scope :alphabetic, -> { order(domain: :asc, username: :asc) }
|
||||
scope :by_domain_accounts, -> { group(:domain).select(:domain, 'COUNT(*) AS accounts_count').order('accounts_count desc') }
|
||||
scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) }
|
||||
@ -153,6 +154,12 @@ class Account < ApplicationRecord
|
||||
self.actor_type = ActiveModel::Type::Boolean.new.cast(val) ? 'Service' : 'Person'
|
||||
end
|
||||
|
||||
def group?
|
||||
actor_type == 'Group'
|
||||
end
|
||||
|
||||
alias group group?
|
||||
|
||||
def acct
|
||||
local? ? username : "#{username}@#{domain}"
|
||||
end
|
||||
|
@ -167,6 +167,18 @@ class MediaAttachment < ApplicationRecord
|
||||
audio? || video?
|
||||
end
|
||||
|
||||
def variant?(other_file_name)
|
||||
return true if file_file_name == other_file_name
|
||||
|
||||
formats = file.styles.values.map(&:format).compact
|
||||
|
||||
return false if formats.empty?
|
||||
|
||||
extension = File.extname(other_file_name)
|
||||
|
||||
formats.include?(extension.delete('.')) && File.basename(other_file_name, extension) == File.basename(file_file_name, File.extname(file_file_name))
|
||||
end
|
||||
|
||||
def to_param
|
||||
shortcode
|
||||
end
|
||||
@ -287,7 +299,7 @@ class MediaAttachment < ApplicationRecord
|
||||
width: width,
|
||||
height: height,
|
||||
size: "#{width}x#{height}",
|
||||
aspect: width.to_f / height.to_f,
|
||||
aspect: width.to_f / height,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -49,6 +49,8 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer
|
||||
'Application'
|
||||
elsif object.bot?
|
||||
'Service'
|
||||
elsif object.group?
|
||||
'Group'
|
||||
else
|
||||
'Person'
|
||||
end
|
||||
|
@ -3,7 +3,7 @@
|
||||
class REST::AccountSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
|
||||
attributes :id, :username, :acct, :display_name, :locked, :bot, :created_at,
|
||||
attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :group, :created_at,
|
||||
:note, :url, :avatar, :avatar_static, :header, :header_static,
|
||||
:followers_count, :following_count, :statuses_count, :last_status_at
|
||||
|
||||
|
@ -4,8 +4,8 @@ class AccountSearchService < BaseService
|
||||
attr_reader :query, :limit, :offset, :options, :account
|
||||
|
||||
def call(query, account = nil, options = {})
|
||||
@acct_hint = query.start_with?('@')
|
||||
@query = query.strip.gsub(/\A@/, '')
|
||||
@acct_hint = query&.start_with?('@')
|
||||
@query = query&.strip&.gsub(/\A@/, '')
|
||||
@limit = options[:limit].to_i
|
||||
@offset = options[:offset].to_i
|
||||
@options = options
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
class SearchService < BaseService
|
||||
def call(query, account, limit, options = {})
|
||||
@query = query.strip
|
||||
@query = query&.strip
|
||||
@account = account
|
||||
@options = options
|
||||
@limit = limit.to_i
|
||||
@ -10,6 +10,8 @@ class SearchService < BaseService
|
||||
@resolve = options[:resolve] || false
|
||||
|
||||
default_results.tap do |results|
|
||||
next if @query.blank?
|
||||
|
||||
if url_query?
|
||||
results.merge!(url_resource_results) unless url_resource.nil? || (@options[:type].present? && url_resource_symbol != @options[:type].to_sym)
|
||||
elsif @query.present?
|
||||
|
@ -7,7 +7,7 @@
|
||||
.fields-group
|
||||
= f.input :redirect_uri, wrapper: :with_block_label, label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri')
|
||||
|
||||
%p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: Doorkeeper.configuration.native_redirect_uri)
|
||||
%p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe
|
||||
|
||||
.field-group
|
||||
.input.with_block_label
|
||||
|
@ -42,7 +42,7 @@ if ENV['S3_ENABLED'] == 'true'
|
||||
|
||||
s3_options: {
|
||||
signature_version: ENV.fetch('S3_SIGNATURE_VERSION') { 'v4' },
|
||||
http_open_timeout: 5,
|
||||
http_open_timeout: ENV.fetch('S3_OPEN_TIMEOUT'){ '5' }.to_i,
|
||||
http_read_timeout: 5,
|
||||
http_idle_timeout: 5,
|
||||
retry_limit: 0,
|
||||
@ -52,7 +52,7 @@ if ENV['S3_ENABLED'] == 'true'
|
||||
if ENV.has_key?('S3_ENDPOINT')
|
||||
Paperclip::Attachment.default_options[:s3_options].merge!(
|
||||
endpoint: ENV['S3_ENDPOINT'],
|
||||
force_path_style: true
|
||||
force_path_style: ENV['S3_OVERRIDE_PATH_STYLE'] != 'true',
|
||||
)
|
||||
|
||||
Paperclip::Attachment.default_options[:url] = ':s3_path_url'
|
||||
@ -89,7 +89,7 @@ else
|
||||
Paperclip::Attachment.default_options.merge!(
|
||||
storage: :filesystem,
|
||||
use_timestamp: true,
|
||||
path: ENV.fetch('PAPERCLIP_ROOT_PATH', ':rails_root/public/system') + '/:class/:attachment/:id_partition/:style/:filename',
|
||||
path: File.join(ENV.fetch('PAPERCLIP_ROOT_PATH', File.join(':rails_root', 'public', 'system')), ':class', ':attachment', ':id_partition', ':style', ':filename'),
|
||||
url: ENV.fetch('PAPERCLIP_ROOT_URL', '/system') + '/:class/:attachment/:id_partition/:style/:filename',
|
||||
)
|
||||
end
|
||||
|
@ -78,6 +78,7 @@ en:
|
||||
roles:
|
||||
admin: Admin
|
||||
bot: Bot
|
||||
group: Group
|
||||
moderator: Mod
|
||||
unavailable: Profile unavailable
|
||||
unfollow: Unfollow
|
||||
|
@ -1,6 +1,66 @@
|
||||
class MigrateAccountConversations < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
class Mention < ApplicationRecord
|
||||
belongs_to :account, inverse_of: :mentions
|
||||
belongs_to :status, -> { unscope(where: :deleted_at) }
|
||||
|
||||
delegate(
|
||||
:username,
|
||||
:acct,
|
||||
to: :account,
|
||||
prefix: true
|
||||
)
|
||||
end
|
||||
|
||||
class Notification < ApplicationRecord
|
||||
belongs_to :account, optional: true
|
||||
belongs_to :activity, polymorphic: true, optional: true
|
||||
|
||||
belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', optional: true
|
||||
belongs_to :mention, foreign_type: 'Mention', foreign_key: 'activity_id', optional: true
|
||||
|
||||
def target_status
|
||||
mention&.status
|
||||
end
|
||||
end
|
||||
|
||||
class AccountConversation < ApplicationRecord
|
||||
belongs_to :account
|
||||
belongs_to :conversation
|
||||
belongs_to :last_status, -> { unscope(where: :deleted_at) }, class_name: 'Status'
|
||||
|
||||
before_validation :set_last_status
|
||||
|
||||
class << self
|
||||
def add_status(recipient, status)
|
||||
conversation = find_or_initialize_by(account: recipient, conversation_id: status.conversation_id, participant_account_ids: participants_from_status(recipient, status))
|
||||
|
||||
return conversation if conversation.status_ids.include?(status.id)
|
||||
|
||||
conversation.status_ids << status.id
|
||||
conversation.unread = status.account_id != recipient.id
|
||||
conversation.save
|
||||
conversation
|
||||
rescue ActiveRecord::StaleObjectError
|
||||
retry
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def participants_from_status(recipient, status)
|
||||
((status.active_mentions.pluck(:account_id) + [status.account_id]).uniq - [recipient.id]).sort
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_last_status
|
||||
self.status_ids = status_ids.sort
|
||||
self.last_status_id = status_ids.last
|
||||
end
|
||||
end
|
||||
|
||||
def up
|
||||
say ''
|
||||
say 'WARNING: This migration may take a *long* time for large instances'
|
||||
|
@ -44,6 +44,105 @@ module Mastodon
|
||||
say("Removed #{processed} media attachments (approx. #{number_to_human_size(aggregate)}) #{dry_run}", :green, true)
|
||||
end
|
||||
|
||||
option :start_after
|
||||
option :dry_run, type: :boolean, default: false
|
||||
desc 'remove-orphans', 'Scan storage and check for files that do not belong to existing media attachments'
|
||||
long_desc <<~LONG_DESC
|
||||
Scans file storage for files that do not belong to existing media attachments. Because this operation
|
||||
requires iterating over every single file individually, it will be slow.
|
||||
|
||||
Please mind that some storage providers charge for the necessary API requests to list objects.
|
||||
LONG_DESC
|
||||
def remove_orphans
|
||||
progress = create_progress_bar(nil)
|
||||
reclaimed_bytes = 0
|
||||
removed = 0
|
||||
dry_run = options[:dry_run] ? ' (DRY RUN)' : ''
|
||||
|
||||
case Paperclip::Attachment.default_options[:storage]
|
||||
when :s3
|
||||
paperclip_instance = MediaAttachment.new.file
|
||||
s3_interface = paperclip_instance.s3_interface
|
||||
bucket = s3_interface.bucket(Paperclip::Attachment.default_options[:s3_credentials][:bucket])
|
||||
last_key = options[:start_after]
|
||||
|
||||
loop do
|
||||
objects = begin
|
||||
begin
|
||||
bucket.objects(start_after: last_key, prefix: 'media_attachments/files/').limit(1000).map { |x| x }
|
||||
rescue => e
|
||||
progress.log(pastel.red("Error fetching list of files: #{e}"))
|
||||
progress.log("If you want to continue from this point, add --start-after=#{last_key} to your command") if last_key
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
break if objects.empty?
|
||||
|
||||
last_key = objects.last.key
|
||||
attachments_map = MediaAttachment.where(id: objects.map { |object| object.key.split('/')[2..-2].join.to_i }).each_with_object({}) { |attachment, map| map[attachment.id] = attachment }
|
||||
|
||||
objects.each do |object|
|
||||
attachment_id = object.key.split('/')[2..-2].join.to_i
|
||||
filename = object.key.split('/').last
|
||||
|
||||
progress.increment
|
||||
|
||||
next unless attachments_map[attachment_id].nil? || !attachments_map[attachment_id].variant?(filename)
|
||||
|
||||
begin
|
||||
object.delete unless options[:dry_run]
|
||||
|
||||
reclaimed_bytes += object.size
|
||||
removed += 1
|
||||
|
||||
progress.log("Found and removed orphan: #{object.key}")
|
||||
rescue => e
|
||||
progress.log(pastel.red("Error processing #{object.key}: #{e}"))
|
||||
end
|
||||
end
|
||||
end
|
||||
when :fog
|
||||
say('The fog storage driver is not supported for this operation at this time', :red)
|
||||
exit(1)
|
||||
when :filesystem
|
||||
require 'find'
|
||||
|
||||
root_path = ENV.fetch('RAILS_ROOT_PATH', File.join(':rails_root', 'public', 'system')).gsub(':rails_root', Rails.root.to_s)
|
||||
|
||||
Find.find(File.join(root_path, 'media_attachments', 'files')) do |path|
|
||||
next if File.directory?(path)
|
||||
|
||||
key = path.gsub("#{root_path}#{File::SEPARATOR}", '')
|
||||
attachment_id = key.split(File::SEPARATOR)[2..-2].join.to_i
|
||||
filename = key.split(File::SEPARATOR).last
|
||||
attachment = MediaAttachment.find_by(id: attachment_id)
|
||||
|
||||
progress.increment
|
||||
|
||||
next unless attachment.nil? || !attachment.variant?(filename)
|
||||
|
||||
begin
|
||||
size = File.size(path)
|
||||
|
||||
File.delete(path) unless options[:dry_run]
|
||||
|
||||
reclaimed_bytes += size
|
||||
removed += 1
|
||||
|
||||
progress.log("Found and removed orphan: #{key}")
|
||||
rescue => e
|
||||
progress.log(pastel.red("Error processing #{key}: #{e}"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
progress.total = progress.progress
|
||||
progress.finish
|
||||
|
||||
say("Removed #{removed} orphans (approx. #{number_to_human_size(reclaimed_bytes)})#{dry_run}", :green, true)
|
||||
end
|
||||
|
||||
option :account, type: :string
|
||||
option :domain, type: :string
|
||||
option :status, type: :numeric
|
||||
|
@ -9,8 +9,8 @@ module Paperclip
|
||||
min_side = [@current_geometry.width, @current_geometry.height].min.to_i
|
||||
options[:geometry] = "#{min_side}x#{min_side}#" if @target_geometry.square? && min_side < @target_geometry.width
|
||||
elsif options[:pixels]
|
||||
width = Math.sqrt(options[:pixels] * (@current_geometry.width.to_f / @current_geometry.height.to_f)).round.to_i
|
||||
height = Math.sqrt(options[:pixels] * (@current_geometry.height.to_f / @current_geometry.width.to_f)).round.to_i
|
||||
width = Math.sqrt(options[:pixels] * (@current_geometry.width.to_f / @current_geometry.height)).round.to_i
|
||||
height = Math.sqrt(options[:pixels] * (@current_geometry.height.to_f / @current_geometry.width)).round.to_i
|
||||
options[:geometry] = "#{width}x#{height}>"
|
||||
end
|
||||
|
||||
|
@ -67,10 +67,11 @@
|
||||
"@babel/preset-env": "^7.7.4",
|
||||
"@babel/preset-react": "^7.7.4",
|
||||
"@babel/runtime": "^7.7.4",
|
||||
"@gamestdio/websocket": "^0.3.2",
|
||||
"@clusterws/cws": "^0.16.0",
|
||||
"array-includes": "^3.0.3",
|
||||
"arrow-key-navigation": "^1.1.0",
|
||||
"autoprefixer": "^9.6.1",
|
||||
"autoprefixer": "^9.7.3",
|
||||
"axios": "^0.19.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
@ -164,7 +165,6 @@
|
||||
"webpack-bundle-analyzer": "^3.6.0",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-merge": "^4.2.1",
|
||||
"websocket.js": "^0.1.12",
|
||||
"wicg-inert": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -176,7 +176,7 @@
|
||||
"eslint-plugin-import": "~2.18.2",
|
||||
"eslint-plugin-jsx-a11y": "~6.2.3",
|
||||
"eslint-plugin-promise": "~4.2.1",
|
||||
"eslint-plugin-react": "~7.16.0",
|
||||
"eslint-plugin-react": "~7.17.0",
|
||||
"jest": "^24.9.0",
|
||||
"raf": "^3.4.1",
|
||||
"react-intl-translations-manager": "^5.0.3",
|
||||
|
@ -12,7 +12,7 @@ end
|
||||
gc_counter = -1
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.example_status_persistence_file_path = ".cache/rspec"
|
||||
config.example_status_persistence_file_path = "tmp/rspec/examples.txt"
|
||||
config.expect_with :rspec do |expectations|
|
||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
||||
end
|
||||
|
226
yarn.lock
226
yarn.lock
@ -964,6 +964,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc"
|
||||
integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA==
|
||||
|
||||
"@gamestdio/websocket@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@gamestdio/websocket/-/websocket-0.3.2.tgz#321ba0976ee30fd14e51dbf8faa85ce7b325f76a"
|
||||
integrity sha512-J3n5SKim+ZoLbe44hRGI/VYAwSMCeIJuBy+FfP6EZaujEpNchPRFcIsVQLWAwpU1bP2Ji63rC+rEUOd1vjUB6Q==
|
||||
|
||||
"@jest/console@^24.7.1":
|
||||
version "24.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545"
|
||||
@ -1793,18 +1798,18 @@ atob@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
autoprefixer@^9.6.1:
|
||||
version "9.6.1"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47"
|
||||
integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==
|
||||
autoprefixer@^9.7.3:
|
||||
version "9.7.3"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.3.tgz#fd42ed03f53de9beb4ca0d61fb4f7268a9bb50b4"
|
||||
integrity sha512-8T5Y1C5Iyj6PgkPSFd0ODvK9DIleuPKUPYniNxybS47g2k2wFgLZ46lGQHlBuGKIAEV8fbCDfKCCRS1tvOgc3Q==
|
||||
dependencies:
|
||||
browserslist "^4.6.3"
|
||||
caniuse-lite "^1.0.30000980"
|
||||
browserslist "^4.8.0"
|
||||
caniuse-lite "^1.0.30001012"
|
||||
chalk "^2.4.2"
|
||||
normalize-range "^0.1.2"
|
||||
num2fraction "^1.2.2"
|
||||
postcss "^7.0.17"
|
||||
postcss-value-parser "^4.0.0"
|
||||
postcss "^7.0.23"
|
||||
postcss-value-parser "^4.0.2"
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
@ -1979,13 +1984,6 @@ babel-runtime@^6.26.0:
|
||||
core-js "^2.4.0"
|
||||
regenerator-runtime "^0.11.0"
|
||||
|
||||
backoff@^2.4.1:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
|
||||
integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=
|
||||
dependencies:
|
||||
precond "0.2"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
@ -2218,14 +2216,14 @@ browserify-zlib@^0.2.0:
|
||||
dependencies:
|
||||
pako "~1.0.5"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.6.3:
|
||||
version "4.6.6"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453"
|
||||
integrity sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==
|
||||
browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.8.0:
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.0.tgz#6f06b0f974a7cc3a84babc2ccc56493668e3c789"
|
||||
integrity sha512-HYnxc/oLRWvJ3TsGegR0SRL/UDnknGq2s/a8dYYEO+kOQ9m9apKoS5oiathLKZdh/e9uE+/J3j92qPlGD/vTqA==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30000984"
|
||||
electron-to-chromium "^1.3.191"
|
||||
node-releases "^1.1.25"
|
||||
caniuse-lite "^1.0.30001012"
|
||||
electron-to-chromium "^1.3.317"
|
||||
node-releases "^1.1.41"
|
||||
|
||||
bser@^2.0.0:
|
||||
version "2.0.0"
|
||||
@ -2414,10 +2412,10 @@ caniuse-api@^3.0.0:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000984:
|
||||
version "1.0.30000986"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000986.tgz#f34350e367cc900509511574817ac092112bf7ab"
|
||||
integrity sha512-pM+LnkoAX0+QnIH3tpW5EnkmfpEoqOD8FAcoBvsl3Xh6DXkgctiCxeCbXphP/k3XJtJzm+zOAJbi6U6IVkpWZQ==
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001012:
|
||||
version "1.0.30001013"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001013.tgz#da2440d4d266a17d40eb79bd19c0c8cc1d029c72"
|
||||
integrity sha512-hOAXaWKuq/UVFgYawxIOdPdyMQdYcwOCDOjnZcKn7wCgFUrhP7smuNZjGLuJlPSgE6aRA4cRJ+bGSrhtEt7ZAg==
|
||||
|
||||
capture-exit@^1.2.0:
|
||||
version "1.2.0"
|
||||
@ -3584,10 +3582,10 @@ ejs@^2.3.4, ejs@^2.6.1:
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228"
|
||||
integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ==
|
||||
|
||||
electron-to-chromium@^1.3.191:
|
||||
version "1.3.203"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.203.tgz#76de1b76eaaf7208e587a26b8e45407535a00abd"
|
||||
integrity sha512-Z1FjJKEBhYrCNmnususVk8khiBabVI/bSJB/295V4ghVt4MFmtbP+mXgRZLQZinEBI469U6FtiGgpXnlLs6qiQ==
|
||||
electron-to-chromium@^1.3.317:
|
||||
version "1.3.321"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.321.tgz#913869f5ec85daabba0e75c9c314b4bf26cdb01e"
|
||||
integrity sha512-jJy/BZK2s2eAjMPXVMSaCmo7/pSY2aKkfQ+LoAb5Wk39qAhyP9r8KU74c4qTgr9cD/lPUhJgReZxxqU0n5puog==
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.5.1"
|
||||
@ -3730,49 +3728,26 @@ error-ex@^1.2.0, error-ex@^1.3.1:
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0:
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
|
||||
integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==
|
||||
es-abstract@^1.10.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.15.0, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0:
|
||||
version "1.16.2"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.2.tgz#4e874331645e9925edef141e74fc4bd144669d34"
|
||||
integrity sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA==
|
||||
dependencies:
|
||||
es-to-primitive "^1.1.1"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.1"
|
||||
is-callable "^1.1.3"
|
||||
is-regex "^1.0.4"
|
||||
|
||||
es-abstract@^1.13.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
|
||||
integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==
|
||||
dependencies:
|
||||
es-to-primitive "^1.2.0"
|
||||
es-to-primitive "^1.2.1"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.1"
|
||||
is-callable "^1.1.4"
|
||||
is-regex "^1.0.4"
|
||||
object-keys "^1.0.12"
|
||||
|
||||
es-abstract@^1.15.0:
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d"
|
||||
integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==
|
||||
dependencies:
|
||||
es-to-primitive "^1.2.0"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.0"
|
||||
is-callable "^1.1.4"
|
||||
is-regex "^1.0.4"
|
||||
object-inspect "^1.6.0"
|
||||
object-inspect "^1.7.0"
|
||||
object-keys "^1.1.1"
|
||||
string.prototype.trimleft "^2.1.0"
|
||||
string.prototype.trimright "^2.1.0"
|
||||
|
||||
es-to-primitive@^1.1.1, es-to-primitive@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
|
||||
integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
|
||||
es-to-primitive@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||
integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
|
||||
dependencies:
|
||||
is-callable "^1.1.4"
|
||||
is-date-object "^1.0.1"
|
||||
@ -3893,6 +3868,11 @@ eslint-module-utils@^2.4.0:
|
||||
debug "^2.6.8"
|
||||
pkg-dir "^2.0.0"
|
||||
|
||||
eslint-plugin-eslint-plugin@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz#a7a00f15a886957d855feacaafee264f039e62d5"
|
||||
integrity sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg==
|
||||
|
||||
eslint-plugin-import@~2.18.2:
|
||||
version "2.18.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6"
|
||||
@ -3930,20 +3910,21 @@ eslint-plugin-promise@~4.2.1:
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a"
|
||||
integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==
|
||||
|
||||
eslint-plugin-react@~7.16.0:
|
||||
version "7.16.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz#9928e4f3e2122ed3ba6a5b56d0303ba3e41d8c09"
|
||||
integrity sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug==
|
||||
eslint-plugin-react@~7.17.0:
|
||||
version "7.17.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz#a31b3e134b76046abe3cd278e7482bd35a1d12d7"
|
||||
integrity sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A==
|
||||
dependencies:
|
||||
array-includes "^3.0.3"
|
||||
doctrine "^2.1.0"
|
||||
eslint-plugin-eslint-plugin "^2.1.0"
|
||||
has "^1.0.3"
|
||||
jsx-ast-utils "^2.2.1"
|
||||
jsx-ast-utils "^2.2.3"
|
||||
object.entries "^1.1.0"
|
||||
object.fromentries "^2.0.0"
|
||||
object.fromentries "^2.0.1"
|
||||
object.values "^1.1.0"
|
||||
prop-types "^15.7.2"
|
||||
resolve "^1.12.0"
|
||||
resolve "^1.13.1"
|
||||
|
||||
eslint-scope@^4.0.3:
|
||||
version "4.0.3"
|
||||
@ -4101,11 +4082,16 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
|
||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
|
||||
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||
|
||||
esutils@^2.0.0, esutils@^2.0.2:
|
||||
esutils@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
|
||||
integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
|
||||
|
||||
esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
@ -4936,10 +4922,10 @@ has-flag@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||
|
||||
has-symbols@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
|
||||
integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
|
||||
has-symbols@^1.0.0, has-symbols@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
||||
|
||||
has-unicode@^2.0.0:
|
||||
version "2.0.1"
|
||||
@ -5789,11 +5775,11 @@ is-svg@^3.0.0:
|
||||
html-comment-regex "^1.1.0"
|
||||
|
||||
is-symbol@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
|
||||
integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
|
||||
integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
|
||||
dependencies:
|
||||
has-symbols "^1.0.0"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
@ -6429,10 +6415,10 @@ jsprim@^1.2.2:
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
jsx-ast-utils@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz#4d4973ebf8b9d2837ee91a8208cc66f3a2776cfb"
|
||||
integrity sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==
|
||||
jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f"
|
||||
integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==
|
||||
dependencies:
|
||||
array-includes "^3.0.3"
|
||||
object.assign "^4.1.0"
|
||||
@ -7194,12 +7180,12 @@ node-pre-gyp@^0.12.0:
|
||||
semver "^5.3.0"
|
||||
tar "^4"
|
||||
|
||||
node-releases@^1.1.25:
|
||||
version "1.1.26"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.26.tgz#f30563edc5c7dc20cf524cc8652ffa7be0762937"
|
||||
integrity sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ==
|
||||
node-releases@^1.1.41:
|
||||
version "1.1.41"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.41.tgz#57674a82a37f812d18e3b26118aefaf53a00afed"
|
||||
integrity sha512-+IctMa7wIs8Cfsa8iYzeaLTFwv5Y4r5jZud+4AnfymzeEXKBCavFX0KBgzVaPVqf0ywa6PrO8/b+bPqdwjGBSg==
|
||||
dependencies:
|
||||
semver "^5.3.0"
|
||||
semver "^6.3.0"
|
||||
|
||||
nopt@^4.0.1:
|
||||
version "4.0.1"
|
||||
@ -7332,22 +7318,17 @@ object-fit-images@^3.2.3:
|
||||
resolved "https://registry.yarnpkg.com/object-fit-images/-/object-fit-images-3.2.4.tgz#6c299d38fdf207746e5d2d46c2877f6f25d15b52"
|
||||
integrity sha512-G+7LzpYfTfqUyrZlfrou/PLLLAPNC52FTy5y1CBywX+1/FkxIloOyQXBmZ3Zxa2AWO+lMF0JTuvqbr7G5e5CWg==
|
||||
|
||||
object-inspect@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
|
||||
integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==
|
||||
object-inspect@^1.6.0, object-inspect@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
|
||||
integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
|
||||
|
||||
object-is@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6"
|
||||
integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=
|
||||
|
||||
object-keys@^1.0.11, object-keys@^1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
|
||||
integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==
|
||||
|
||||
object-keys@^1.1.1:
|
||||
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||
@ -7379,16 +7360,6 @@ object.entries@^1.0.4, object.entries@^1.1.0:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
|
||||
object.fromentries@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab"
|
||||
integrity sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==
|
||||
dependencies:
|
||||
define-properties "^1.1.2"
|
||||
es-abstract "^1.11.0"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.1"
|
||||
|
||||
object.fromentries@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.1.tgz#050f077855c7af8ae6649f45c80b16ee2d31e704"
|
||||
@ -8319,10 +8290,10 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1:
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
|
||||
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
|
||||
|
||||
postcss-value-parser@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d"
|
||||
integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ==
|
||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9"
|
||||
integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==
|
||||
|
||||
postcss@^5.0.16:
|
||||
version "5.2.18"
|
||||
@ -8334,10 +8305,10 @@ postcss@^5.0.16:
|
||||
source-map "^0.5.6"
|
||||
supports-color "^3.2.3"
|
||||
|
||||
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.5, postcss@^7.0.6:
|
||||
version "7.0.17"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f"
|
||||
integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==
|
||||
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.6:
|
||||
version "7.0.23"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.23.tgz#9f9759fad661b15964f3cfc3140f66f1e05eadc1"
|
||||
integrity sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
@ -8365,11 +8336,6 @@ postgres-interval@^1.1.0:
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
precond@0.2:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
|
||||
integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=
|
||||
|
||||
prelude-ls@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
@ -8716,11 +8682,16 @@ react-intl@^2.9.0:
|
||||
intl-relativeformat "^2.1.0"
|
||||
invariant "^2.1.1"
|
||||
|
||||
react-is@^16.10.2, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
|
||||
react-is@^16.10.2, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
|
||||
version "16.11.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa"
|
||||
integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==
|
||||
|
||||
react-is@^16.8.1:
|
||||
version "16.12.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
|
||||
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
|
||||
|
||||
react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
@ -9281,7 +9252,7 @@ resolve@1.1.7:
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
|
||||
|
||||
resolve@^1.11.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1:
|
||||
resolve@^1.11.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
|
||||
integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
|
||||
@ -10975,13 +10946,6 @@ websocket-extensions@>=0.1.1:
|
||||
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
|
||||
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
|
||||
|
||||
websocket.js@^0.1.12:
|
||||
version "0.1.12"
|
||||
resolved "https://registry.yarnpkg.com/websocket.js/-/websocket.js-0.1.12.tgz#46c980787c57ebc8edcf44a0263e5d639367b85b"
|
||||
integrity sha1-RsmAeHxX68jtz0SgJj5dY5NnuFs=
|
||||
dependencies:
|
||||
backoff "^2.4.1"
|
||||
|
||||
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
|
||||
|
Loading…
Reference in New Issue
Block a user