Merge branch 'master' into fix/cache_blocking
This commit is contained in:
commit
acd33101c5
48 changed files with 453 additions and 184 deletions
|
@ -24,8 +24,10 @@ const makeGetStatusIds = () => createSelector([
|
|||
|
||||
if (columnSettings.getIn(['regex', 'body'], '').trim().length > 0) {
|
||||
try {
|
||||
const regex = new RegExp(columnSettings.getIn(['regex', 'body']).trim(), 'i');
|
||||
showStatus = showStatus && !regex.test(statusForId.get('reblog') ? statuses.getIn([statusForId.get('reblog'), 'content']) : statusForId.get('content'));
|
||||
if (showStatus) {
|
||||
const regex = new RegExp(columnSettings.getIn(['regex', 'body']).trim(), 'i');
|
||||
showStatus = !regex.test(statusForId.get('reblog') ? statuses.getIn([statusForId.get('reblog'), 'unescaped_content']) : statusForId.get('unescaped_content'));
|
||||
}
|
||||
} catch(e) {
|
||||
// Bad regex, don't affect filters
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ const fr = {
|
|||
"navigation_bar.favourites": "Favoris",
|
||||
"navigation_bar.info": "Plus d'informations",
|
||||
"navigation_bar.logout": "Déconnexion",
|
||||
"navigation_bar.mutes": "Utilisateurs muets",
|
||||
"navigation_bar.follow_requests": "Demandes de suivi",
|
||||
"reply_indicator.cancel": "Annuler",
|
||||
"search.placeholder": "Rechercher",
|
||||
|
|
|
@ -1,121 +1,125 @@
|
|||
const ja = {
|
||||
"column_back_button.label": "戻る",
|
||||
"lightbox.close": "閉じる",
|
||||
"loading_indicator.label": "読み込み中...",
|
||||
"status.mention": "@{name} さんへの返信",
|
||||
"status.delete": "削除",
|
||||
"status.reply": "返信",
|
||||
"status.reblog": "ブースト",
|
||||
"status.favourite": "お気に入り",
|
||||
"status.reblogged_by": "{name} さんにブーストされました",
|
||||
"status.sensitive_warning": "不適切なコンテンツ",
|
||||
"status.sensitive_toggle": "クリックして表示",
|
||||
"status.show_more": "もっと見る",
|
||||
"status.load_more": "もっと見る",
|
||||
"status.show_less": "隠す",
|
||||
"status.open": "Expand this status",
|
||||
"status.report": "@{name} さんを通報",
|
||||
"status.media_hidden": "非表示のメデイア",
|
||||
"video_player.toggle_sound": "音の切り替え",
|
||||
"account.mention": "@{name} さんに返信",
|
||||
"account.block": "@{name} さんをブロック",
|
||||
"account.disclaimer": "このユーザーは他のインスタンスに所属しているため、数字が正確で無い場合があります。",
|
||||
"account.edit_profile": "プロフィールを編集",
|
||||
"account.follow": "フォロー",
|
||||
"account.followers": "フォロワー",
|
||||
"account.follows": "フォロー",
|
||||
"account.follows_you": "フォローされています",
|
||||
"account.mention": "@{name} さんに返信",
|
||||
"account.mute": "ミュート",
|
||||
"account.posts": "投稿",
|
||||
"account.report": "@{name}を通報する",
|
||||
"account.requested": "承認待ち",
|
||||
"account.unblock": "@{name} さんのブロックを解除",
|
||||
"account.unfollow": "フォロー解除",
|
||||
"account.block": "@{name} さんをブロック",
|
||||
"account.mute": "ミュート",
|
||||
"account.unmute": "ミュート解除",
|
||||
"account.follow": "フォロー",
|
||||
"account.report": "@{name}を通報する",
|
||||
"account.posts": "投稿",
|
||||
"account.follows": "フォロー",
|
||||
"account.followers": "フォロワー",
|
||||
"account.follows_you": "フォローされています",
|
||||
"account.requested": "承認待ち",
|
||||
"follow_request.authorize": "許可",
|
||||
"follow_request.reject": "拒否",
|
||||
"getting_started.heading": "スタート",
|
||||
"getting_started.about_addressing": "ドメインとユーザー名を知っているなら検索フォームに入力すればフォローできます。",
|
||||
"getting_started.about_shortcuts": "対象のアカウントがあなたと同じドメインのユーザーならばユーザー名のみで検索できます。これは返信のときも一緒です。",
|
||||
"getting_started.open_source_notice": "Mastodon はオープンソースソフトウェアです。誰でも GitHub({github})から開発に参加したり、問題を報告したりできます。 {apps}",
|
||||
"getting_started.apps": "さまざまなアプリで利用できます。",
|
||||
"column.home": "ホーム",
|
||||
"boost_modal.combo": "次からは{combo}を押せば、これをスキップできます。",
|
||||
"column.blocks": "ブロックしたユーザー",
|
||||
"column.community": "ローカルタイムライン",
|
||||
"column.public": "連合タイムライン",
|
||||
"column.notifications": "通知",
|
||||
"column.favourites": "お気に入り",
|
||||
"tabs_bar.compose": "投稿",
|
||||
"tabs_bar.home": "ホーム",
|
||||
"tabs_bar.mentions": "返信",
|
||||
"tabs_bar.local_timeline": "ローカル",
|
||||
"tabs_bar.federated_timeline": "連合",
|
||||
"tabs_bar.notifications": "通知",
|
||||
"column.follow_requests": "フォローリクエスト",
|
||||
"column.home": "ホーム",
|
||||
"column.mutes": "ミュートしたユーザー",
|
||||
"column.notifications": "通知",
|
||||
"column.public": "連合タイムライン",
|
||||
"column_back_button.label": "戻る",
|
||||
"compose_form.placeholder": "今なにしてる?",
|
||||
"compose_form.privacy_disclaimer": "あなたの非公開トゥートは返信先のユーザー(at {domains})に公開されます。{domainsCount, plural, one {that server} other {those servers}}を信頼しますか?投稿のプライバシー保護はMastodonサーバー内でのみ有効です。 もし{domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}ならばあなたの投稿のプライバシーは保護されず、ブーストされたり予期しないユーザーに見られる可能性があります。",
|
||||
"compose_form.publish": "トゥート",
|
||||
"compose_form.sensitive": "メディアを不適切なコンテンツとしてマークする",
|
||||
"compose_form.spoiler": "テキストを隠す",
|
||||
"compose_form.spoiler_placeholder": "内容注意メッセージ",
|
||||
"compose_form.private": "非公開にする",
|
||||
"compose_form.privacy_disclaimer": "あなたの非公開トゥートは返信先のユーザー(at {domains})に公開されます。{domainsCount, plural, one {that server} other {those servers}}を信頼しますか?投稿のプライバシー保護はMastodonサーバー内でのみ有効です。 もし{domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}ならばあなたの投稿のプライバシーは保護されず、ブーストされたり予期しないユーザーに見られる可能性があります。",
|
||||
"compose_form.unlisted": "公開タイムラインに表示しない",
|
||||
"privacy.public.short": "公開",
|
||||
"privacy.public.long": "公開TLに投稿する",
|
||||
"privacy.unlisted.short": "未収載",
|
||||
"privacy.unlisted.long": "公開TLで表示しない",
|
||||
"privacy.private.short": "非公開",
|
||||
"privacy.private.long": "フォロワーだけに公開",
|
||||
"privacy.direct.short": "ダイレクト",
|
||||
"privacy.direct.long": "含んだユーザーだけに公開",
|
||||
"privacy.change": "投稿のプライバシーを変更",
|
||||
"report.heading": "新規通報",
|
||||
"report.placeholder": "コメント",
|
||||
"report.target": "問題のユーザー",
|
||||
"report.submit": "通報する",
|
||||
"navigation_bar.edit_profile": "プロフィールを編集",
|
||||
"navigation_bar.preferences": "ユーザー設定",
|
||||
"navigation_bar.community_timeline": "ローカルタイムライン",
|
||||
"navigation_bar.public_timeline": "連合タイムライン",
|
||||
"navigation_bar.logout": "ログアウト",
|
||||
"navigation_bar.favourites": "お気に入り",
|
||||
"navigation_bar.blocks": "ブロックしたユーザー",
|
||||
"navigation_bar.info": "サーバー情報",
|
||||
"reply_indicator.cancel": "キャンセル",
|
||||
"search.placeholder": "検索",
|
||||
"search.account": "アカウント",
|
||||
"search.hashtag": "ハッシュタグ",
|
||||
"search.status_by": "{uuuname}からの投稿",
|
||||
"search_results.total": "{count} 件",
|
||||
"upload_area.title": "ファイルをこちらにドラッグしてください",
|
||||
"upload_button.label": "メディアを追加",
|
||||
"upload_form.undo": "やり直す",
|
||||
"notification.follow": "{name} さんにフォローされました",
|
||||
"notification.favourite": "{name} さんがあなたのトゥートをお気に入りに登録しました",
|
||||
"notification.reblog": "{name} さんがあなたのトゥートをブーストしました",
|
||||
"notification.mention": "{name} さんがあなたに返信しました",
|
||||
"notifications.clear": "通知を片付ける",
|
||||
"notifications.clear_confirmation": "通知を全部片付けます。大丈夫ですか?",
|
||||
"notifications.column_settings.alert": "デスクトップ通知",
|
||||
"notifications.column_settings.show": "カラムに表示",
|
||||
"notifications.column_settings.follow": "新しいフォロワー",
|
||||
"notifications.column_settings.favourite": "お気に入り",
|
||||
"notifications.column_settings.mention": "返信",
|
||||
"notifications.column_settings.reblog": "ブースト",
|
||||
"notifications.column_settings.sound": "通知音を再生",
|
||||
"compose_form.spoiler_placeholder": "閲覧注意",
|
||||
"emoji_button.label": "絵文字を追加",
|
||||
"empty_column.community": "ローカルタイムラインはまだ使われていません。何か書いてみましょう!",
|
||||
"empty_column.hashtag": "このハッシュタグはまだ使われていません。",
|
||||
"empty_column.home": "まだ誰もフォローしていません。{public}を見に行くか、検索を使って他のユーザーを見つけましょう。",
|
||||
"empty_column.home.public_timeline": "連合タイムライン",
|
||||
"empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。",
|
||||
"empty_column.public": "ここにはまだ何もありません!公開で何かを投稿したり、他のインスタンスのユーザーをフォローしたりしていっぱいにしましょう!",
|
||||
"empty_column.hashtag": "このハッシュタグはまだ使っていません。",
|
||||
"upload_progress.label": "アップロード中…",
|
||||
"emoji_button.label": "絵文字を追加",
|
||||
"follow_request.authorize": "許可",
|
||||
"follow_request.reject": "拒否",
|
||||
"getting_started.apps": "さまざまなアプリで利用できます。",
|
||||
"getting_started.heading": "スタート",
|
||||
"getting_started.open_source_notice": "Mastodon はオープンソースソフトウェアです。誰でも GitHub({github})から開発に参加したり、問題を報告したりできます。 {apps}",
|
||||
"home.column_settings.advanced": "上級者向け",
|
||||
"home.column_settings.basic": "シンプル",
|
||||
"home.column_settings.advanced": "エキスパート",
|
||||
"home.column_settings.filter_regex": "正規表現でフィルター",
|
||||
"home.column_settings.show_reblogs": "ブースト表示",
|
||||
"home.column_settings.show_replies": "返信表示",
|
||||
"home.column_settings.filter_regex": "正規表現でフィルター",
|
||||
"home.settings": "カラム設定",
|
||||
"notifications.settings": "カラム設定",
|
||||
"lightbox.close": "閉じる",
|
||||
"loading_indicator.label": "読み込み中...",
|
||||
"media_gallery.toggle_visible": "表示切り替え",
|
||||
"missing_indicator.label": "見つかりません",
|
||||
"boost_modal.combo": "次は{combo}を押せば、これをスキップできます。"
|
||||
"navigation_bar.blocks": "ブロックしたユーザー",
|
||||
"navigation_bar.community_timeline": "ローカルタイムライン",
|
||||
"navigation_bar.edit_profile": "プロフィールを編集",
|
||||
"navigation_bar.favourites": "お気に入り",
|
||||
"navigation_bar.follow_requests": "フォローリクエスト",
|
||||
"navigation_bar.info": "サーバー情報",
|
||||
"navigation_bar.logout": "ログアウト",
|
||||
"navigation_bar.mutes": "ミュートしたユーザー",
|
||||
"navigation_bar.preferences": "ユーザー設定",
|
||||
"navigation_bar.public_timeline": "連合タイムライン",
|
||||
"notification.favourite": "{name} さんがあなたのトゥートをお気に入りに登録しました",
|
||||
"notification.follow": "{name} さんにフォローされました",
|
||||
"notification.mention": "{name} さんがあなたに返信しました",
|
||||
"notification.reblog": "{name} さんがあなたのトゥートをブーストしました",
|
||||
"notifications.clear": "通知を消去",
|
||||
"notifications.clear_confirmation": "本当に通知を消去しますか?",
|
||||
"notifications.column_settings.alert": "デスクトップ通知",
|
||||
"notifications.column_settings.favourite": "お気に入り",
|
||||
"notifications.column_settings.follow": "新しいフォロワー",
|
||||
"notifications.column_settings.mention": "返信",
|
||||
"notifications.column_settings.reblog": "ブースト",
|
||||
"notifications.column_settings.show": "カラムに表示",
|
||||
"notifications.column_settings.sound": "通知音を再生",
|
||||
"notifications.settings": "カラム設定",
|
||||
"privacy.change": "投稿のプライバシーを変更",
|
||||
"privacy.direct.long": "メンションしたユーザーだけに公開",
|
||||
"privacy.direct.short": "ダイレクト",
|
||||
"privacy.private.long": "フォロワーだけに公開",
|
||||
"privacy.private.short": "非公開",
|
||||
"privacy.public.long": "公開TLに投稿する",
|
||||
"privacy.public.short": "公開",
|
||||
"privacy.unlisted.long": "公開TLで表示しない",
|
||||
"privacy.unlisted.short": "未収載",
|
||||
"reply_indicator.cancel": "キャンセル",
|
||||
"report.heading": "新規通報",
|
||||
"report.placeholder": "コメント",
|
||||
"report.submit": "通報する",
|
||||
"report.target": "問題のユーザー",
|
||||
"search.placeholder": "検索",
|
||||
"search.status_by": "{name}からの投稿",
|
||||
"search_results.total": "{count} {count, plural, one {result} other {results}} 件",
|
||||
"status.delete": "削除",
|
||||
"status.favourite": "お気に入り",
|
||||
"status.load_more": "もっと見る",
|
||||
"status.media_hidden": "非表示のメデイア",
|
||||
"status.mention": "@{name} さんへの返信",
|
||||
"status.open": "詳細を表示",
|
||||
"status.reblog": "ブースト",
|
||||
"status.reblogged_by": "{name} さんにブーストされました",
|
||||
"status.reply": "返信",
|
||||
"status.report": "@{name} さんを通報",
|
||||
"status.sensitive_toggle": "クリックして表示",
|
||||
"status.sensitive_warning": "不適切なコンテンツ",
|
||||
"status.show_less": "隠す",
|
||||
"status.show_more": "もっと見る",
|
||||
"tabs_bar.compose": "投稿",
|
||||
"tabs_bar.federated_timeline": "連合",
|
||||
"tabs_bar.home": "ホーム",
|
||||
"tabs_bar.local_timeline": "ローカル",
|
||||
"tabs_bar.notifications": "通知",
|
||||
"upload_area.title": "ドラッグ&ドロップでアップロード",
|
||||
"upload_button.label": "メディアを追加",
|
||||
"upload_form.undo": "やり直す",
|
||||
"upload_progress.label": "アップロード中…",
|
||||
"video_player.expand": "動画の詳細",
|
||||
"video_player.toggle_sound": "音の切り替え",
|
||||
"video_player.toggle_visible": "表示切り替え",
|
||||
"video_player.video_error": "動画の再生に失敗しました",
|
||||
};
|
||||
|
||||
export default ja;
|
||||
|
|
|
@ -48,6 +48,9 @@ const normalizeStatus = (state, status) => {
|
|||
normalStatus.reblog = status.reblog.id;
|
||||
}
|
||||
|
||||
const linebreakComplemented = status.content.replace(/<br \/>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
||||
normalStatus.unescaped_content = new DOMParser().parseFromString(linebreakComplemented, 'text/html').documentElement.textContent;
|
||||
|
||||
return state.update(status.id, Immutable.Map(), map => map.mergeDeep(Immutable.fromJS(normalStatus)));
|
||||
};
|
||||
|
||||
|
|
|
@ -1203,6 +1203,10 @@ a.status__content__spoiler-link {
|
|||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.spoiler-input__input {
|
||||
|
@ -1267,6 +1271,10 @@ a.status__content__spoiler-link {
|
|||
color: $color5;
|
||||
border-bottom-color: $color4;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@import 'boost';
|
||||
|
@ -1906,6 +1914,10 @@ button.icon-button.active i.fa-retweet {
|
|||
&:focus {
|
||||
background: lighten($color1, 4%);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.search__icon {
|
||||
|
|
|
@ -15,16 +15,26 @@ module Admin
|
|||
|
||||
if @domain_block.save
|
||||
DomainBlockWorker.perform_async(@domain_block.id)
|
||||
redirect_to admin_domain_blocks_path, notice: 'Domain block is now being processed'
|
||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_block.created_msg')
|
||||
else
|
||||
render action: :new
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@domain_block = DomainBlock.find(params[:id])
|
||||
end
|
||||
|
||||
def destroy
|
||||
@domain_block = DomainBlock.find(params[:id])
|
||||
UnblockDomainService.new.call(@domain_block, resource_params[:retroactive])
|
||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_block.destroyed_msg')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resource_params
|
||||
params.require(:domain_block).permit(:domain, :severity)
|
||||
params.require(:domain_block).permit(:domain, :severity, :reject_media, :retroactive)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,9 @@ class ApplicationController < ActionController::Base
|
|||
force_ssl if: "Rails.env.production? && ENV['LOCAL_HTTPS'] == 'true'"
|
||||
|
||||
include Localized
|
||||
helper_method :current_account, :single_user_mode?
|
||||
|
||||
helper_method :current_account
|
||||
helper_method :single_user_mode?
|
||||
|
||||
rescue_from ActionController::RoutingError, with: :not_found
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
class DomainBlock < ApplicationRecord
|
||||
enum severity: [:silence, :suspend]
|
||||
|
||||
attr_accessor :retroactive
|
||||
|
||||
validates :domain, presence: true, uniqueness: true
|
||||
|
||||
def self.blocked?(domain)
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Import < ApplicationRecord
|
||||
FILE_TYPES = ['text/plain', 'text/csv'].freeze
|
||||
|
||||
self.inheritance_column = false
|
||||
|
||||
belongs_to :account, required: true
|
||||
|
||||
enum type: [:following, :blocking, :muting]
|
||||
|
||||
belongs_to :account
|
||||
|
||||
FILE_TYPES = ['text/plain', 'text/csv'].freeze
|
||||
validates :type, presence: true
|
||||
|
||||
has_attached_file :data, url: '/system/:hash.:extension', hash_secret: ENV['PAPERCLIP_SECRET']
|
||||
validates_attachment_content_type :data, content_type: FILE_TYPES
|
||||
|
|
|
@ -110,6 +110,10 @@ class Status < ApplicationRecord
|
|||
results
|
||||
end
|
||||
|
||||
def non_sensitive_with_media?
|
||||
!sensitive? && media_attachments.any?
|
||||
end
|
||||
|
||||
class << self
|
||||
def as_home_timeline(account)
|
||||
where(account: [account] + account.following)
|
||||
|
|
|
@ -3,12 +3,34 @@
|
|||
class BlockDomainService < BaseService
|
||||
def call(domain_block)
|
||||
if domain_block.silence?
|
||||
Account.where(domain: domain_block.domain).update_all(silenced: true)
|
||||
silence_accounts!(domain_block.domain)
|
||||
clear_media!(domain_block.domain) if domain_block.reject_media?
|
||||
else
|
||||
Account.where(domain: domain_block.domain).find_each do |account|
|
||||
account.subscription(api_subscription_url(account.id)).unsubscribe if account.subscribed?
|
||||
SuspendAccountService.new.call(account)
|
||||
end
|
||||
suspend_accounts!(domain_block.domain)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def silence_accounts!(domain)
|
||||
Account.where(domain: domain).update_all(silenced: true)
|
||||
end
|
||||
|
||||
def clear_media!(domain)
|
||||
Account.where(domain: domain).find_each do |account|
|
||||
account.avatar.destroy
|
||||
account.header.destroy
|
||||
end
|
||||
|
||||
MediaAttachment.where(account: Account.where(domain: domain)).find_each do |attachment|
|
||||
attachment.file.destroy
|
||||
end
|
||||
end
|
||||
|
||||
def suspend_accounts!(domain)
|
||||
Account.where(domain: domain).where(suspended: false).find_each do |account|
|
||||
account.subscription(api_subscription_url(account.id)).unsubscribe if account.subscribed?
|
||||
SuspendAccountService.new.call(account)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ class FollowRemoteAccountService < BaseService
|
|||
return Account.find_local(username) if TagManager.instance.local_domain?(domain)
|
||||
|
||||
account = Account.find_remote(username, domain)
|
||||
return account unless account&.last_webfingered_at.nil? || 1.day.from_now(account.last_webfingered_at) < Time.now.utc
|
||||
return account unless account_needs_webfinger_update?(account)
|
||||
|
||||
Rails.logger.debug "Looking up webfinger for #{uri}"
|
||||
|
||||
|
@ -62,6 +62,10 @@ class FollowRemoteAccountService < BaseService
|
|||
|
||||
private
|
||||
|
||||
def account_needs_webfinger_update?(account)
|
||||
account&.last_webfingered_at.nil? || account.last_webfingered_at <= 1.day.ago
|
||||
end
|
||||
|
||||
def get_feed(url)
|
||||
response = http_client.get(Addressable::URI.parse(url))
|
||||
[response.to_s, Nokogiri::XML(response)]
|
||||
|
|
|
@ -179,12 +179,12 @@ class ProcessFeedService < BaseService
|
|||
end
|
||||
|
||||
def hashtags_from_xml(parent, xml)
|
||||
tags = xml.xpath('./xmlns:category', xmlns: TagManager::XMLNS).map { |category| category['term'] }.select { |t| !t.blank? }
|
||||
tags = xml.xpath('./xmlns:category', xmlns: TagManager::XMLNS).map { |category| category['term'] }.select(&:present?)
|
||||
ProcessHashtagsService.new.call(parent, tags)
|
||||
end
|
||||
|
||||
def media_from_xml(parent, xml)
|
||||
return if DomainBlock.find_by(domain: parent.account.domain)&.reject_media?
|
||||
do_not_download = DomainBlock.find_by(domain: parent.account.domain)&.reject_media?
|
||||
|
||||
xml.xpath('./xmlns:link[@rel="enclosure"]', xmlns: TagManager::XMLNS).each do |link|
|
||||
next unless link['href']
|
||||
|
@ -192,7 +192,11 @@ class ProcessFeedService < BaseService
|
|||
media = MediaAttachment.where(status: parent, remote_url: link['href']).first_or_initialize(account: parent.account, status: parent, remote_url: link['href'])
|
||||
parsed_url = URI.parse(link['href'])
|
||||
|
||||
next if !%w(http https).include?(parsed_url.scheme) || parsed_url.host.empty?
|
||||
next if !%w[http https].include?(parsed_url.scheme) || parsed_url.host.empty?
|
||||
|
||||
media.save
|
||||
|
||||
next if do_not_download
|
||||
|
||||
begin
|
||||
media.file_remote_url = link['href']
|
||||
|
|
|
@ -13,6 +13,7 @@ class SuspendAccountService < BaseService
|
|||
|
||||
def purge_content
|
||||
@account.statuses.reorder(nil).find_each do |status|
|
||||
# This federates out deletes to previous followers
|
||||
RemoveStatusService.new.call(status)
|
||||
end
|
||||
|
||||
|
@ -29,9 +30,7 @@ class SuspendAccountService < BaseService
|
|||
@account.display_name = ''
|
||||
@account.note = ''
|
||||
@account.avatar.destroy
|
||||
@account.avatar.clear
|
||||
@account.header.destroy
|
||||
@account.header.clear
|
||||
@account.save!
|
||||
end
|
||||
|
||||
|
|
15
app/services/unblock_domain_service.rb
Normal file
15
app/services/unblock_domain_service.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UnblockDomainService < BaseService
|
||||
def call(domain_block, retroactive)
|
||||
if retroactive
|
||||
if domain_block.silence?
|
||||
Account.where(domain: domain_block.domain).update_all(silenced: false)
|
||||
else
|
||||
Account.where(domain: domain_block.domain).update_all(suspended: false)
|
||||
end
|
||||
end
|
||||
|
||||
domain_block.destroy
|
||||
end
|
||||
end
|
|
@ -6,6 +6,7 @@ class UnfollowService < BaseService
|
|||
# @param [Account] target_account Which to unfollow
|
||||
def call(source_account, target_account)
|
||||
follow = source_account.unfollow!(target_account)
|
||||
return unless follow
|
||||
NotificationWorker.perform_async(build_xml(follow), source_account.id, target_account.id) unless target_account.local?
|
||||
UnmergeWorker.perform_async(target_account.id, source_account.id)
|
||||
end
|
||||
|
|
|
@ -71,6 +71,6 @@
|
|||
%p Dette dokumentet er lisensiert under CC-BY-SA. De ble sist oppdatert 12. april 2017.
|
||||
|
||||
%p
|
||||
Dokumentet er en adoptert og endret versjon fra
|
||||
Dokumentet er en adoptert og endret versjon fra
|
||||
= succeed '.' do
|
||||
= link_to 'Discourse privacy policy', 'https://github.com/discourse/discourse'
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
.card.h-card.p-author{ style: "background-image: url(#{@account.header.url( :original)})" }
|
||||
- if user_signed_in? && current_account.id != @account.id && !current_account.requested?(@account)
|
||||
.card.h-card.p-author{ style: "background-image: url(#{account.header.url( :original)})" }
|
||||
- if user_signed_in? && current_account.id != account.id && !current_account.requested?(account)
|
||||
.controls
|
||||
- if current_account.following?(@account)
|
||||
= link_to t('accounts.unfollow'), unfollow_account_path(@account), data: { method: :post }, class: 'button'
|
||||
- if current_account.following?(account)
|
||||
= link_to t('accounts.unfollow'), unfollow_account_path(account), data: { method: :post }, class: 'button'
|
||||
- else
|
||||
= link_to t('accounts.follow'), follow_account_path(@account), data: { method: :post }, class: 'button'
|
||||
= link_to t('accounts.follow'), follow_account_path(account), data: { method: :post }, class: 'button'
|
||||
- elsif !user_signed_in?
|
||||
.controls
|
||||
.remote-follow
|
||||
= link_to t('accounts.remote_follow'), account_remote_follow_path(@account), class: 'button'
|
||||
.avatar= image_tag @account.avatar.url(:original), class: 'u-photo'
|
||||
= link_to t('accounts.remote_follow'), account_remote_follow_path(account), class: 'button'
|
||||
.avatar= image_tag account.avatar.url(:original), class: 'u-photo'
|
||||
%h1.name
|
||||
%span.p-name.emojify= display_name(@account)
|
||||
%span.p-name.emojify= display_name(account)
|
||||
%small
|
||||
%span= "@#{@account.username}"
|
||||
= fa_icon('lock') if @account.locked?
|
||||
%span= "@#{account.username}"
|
||||
= fa_icon('lock') if account.locked?
|
||||
.details
|
||||
.bio
|
||||
.account__header__content.p-note.emojify= Formatter.instance.simplified_format(@account)
|
||||
.account__header__content.p-note.emojify= Formatter.instance.simplified_format(account)
|
||||
|
||||
.details-counters
|
||||
.counter{ class: active_nav_class(short_account_url(@account)) }
|
||||
= link_to short_account_url(@account), class: 'u-url u-uid' do
|
||||
.counter{ class: active_nav_class(short_account_url(account)) }
|
||||
= link_to short_account_url(account), class: 'u-url u-uid' do
|
||||
%span.counter-label= t('accounts.posts')
|
||||
%span.counter-number= number_with_delimiter @account.statuses_count
|
||||
.counter{ class: active_nav_class(following_account_url(@account)) }
|
||||
= link_to following_account_url(@account) do
|
||||
%span.counter-number= number_with_delimiter account.statuses_count
|
||||
.counter{ class: active_nav_class(following_account_url(account)) }
|
||||
= link_to following_account_url(account) do
|
||||
%span.counter-label= t('accounts.following')
|
||||
%span.counter-number= number_with_delimiter @account.following_count
|
||||
.counter{ class: active_nav_class(followers_account_url(@account)) }
|
||||
= link_to followers_account_url(@account) do
|
||||
%span.counter-number= number_with_delimiter account.following_count
|
||||
.counter{ class: active_nav_class(followers_account_url(account)) }
|
||||
= link_to followers_account_url(account) do
|
||||
%span.counter-label= t('accounts.followers')
|
||||
%span.counter-number= number_with_delimiter @account.followers_count
|
||||
%span.counter-number= number_with_delimiter account.followers_count
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for :page_title do
|
||||
= t('accounts.people_who_follow', name: display_name(@account))
|
||||
|
||||
= render partial: 'header'
|
||||
= render 'header', account: @account
|
||||
|
||||
.accounts-grid
|
||||
- if @followers.empty?
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for :page_title do
|
||||
= t('accounts.people_followed_by', name: display_name(@account))
|
||||
|
||||
= render partial: 'header'
|
||||
= render 'header', account: @account
|
||||
|
||||
.accounts-grid
|
||||
- if @following.empty?
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
.h-feed
|
||||
%data.p-name{ value: "#{@account.username} on #{Rails.configuration.x.local_domain}" }/
|
||||
|
||||
= render partial: 'header'
|
||||
= render 'header', account: @account
|
||||
|
||||
- if @statuses.empty?
|
||||
.accounts-grid
|
||||
|
|
|
@ -6,12 +6,19 @@
|
|||
%tr
|
||||
%th= t('admin.domain_block.domain')
|
||||
%th= t('admin.domain_block.severity')
|
||||
%th= t('admin.domain_block.reject_media')
|
||||
%th
|
||||
%tbody
|
||||
- @blocks.each do |block|
|
||||
%tr
|
||||
%td
|
||||
%samp= block.domain
|
||||
%td= block.severity
|
||||
%td= t("admin.domain_block.severities.#{block.severity}")
|
||||
%td
|
||||
- if block.reject_media? || block.suspend?
|
||||
%i.fa.fa-check
|
||||
%td
|
||||
= table_link_to 'undo', t('admin.domain_block.undo'), admin_domain_block_path(block)
|
||||
|
||||
= paginate @blocks
|
||||
= link_to t('admin.domain_block.add_new'), new_admin_domain_block_path, class: 'button'
|
||||
|
|
|
@ -10,5 +10,8 @@
|
|||
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| I18n.t("admin.domain_block.new.severity.#{type}") }
|
||||
|
||||
%p.hint= t('admin.domain_block.new.severity.desc_html')
|
||||
|
||||
= f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_block.reject_media'), hint: I18n.t('admin.domain_block.reject_media_hint')
|
||||
|
||||
.actions
|
||||
= f.button :button, t('admin.domain_block.new.create'), type: :submit
|
||||
|
|
9
app/views/admin/domain_blocks/show.html.haml
Normal file
9
app/views/admin/domain_blocks/show.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
|||
- content_for :page_title do
|
||||
= t('admin.domain_block.show.title', domain: @domain_block.domain)
|
||||
|
||||
= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :delete do |f|
|
||||
|
||||
= f.input :retroactive, as: :boolean, wrapper: :with_label, label: I18n.t("admin.domain_block.show.retroactive.#{@domain_block.severity}"), hint: I18n.t('admin.domain_block.show.affected_accounts', count: Account.where(domain: @domain_block.domain).count)
|
||||
|
||||
.actions
|
||||
= f.button :button, t('admin.domain_block.show.undo'), type: :submit
|
|
@ -1,5 +1,5 @@
|
|||
attributes :id, :remote_url, :type
|
||||
|
||||
node(:url) { |media| full_asset_url(media.file.url(:original)) }
|
||||
node(:preview_url) { |media| full_asset_url(media.file.url(:small)) }
|
||||
node(:url) { |media| media.file.blank? ? media.remote_url : full_asset_url(media.file.url(:original)) }
|
||||
node(:preview_url) { |media| media.file.blank? ? media.remote_url : full_asset_url(media.file.url(:small)) }
|
||||
node(:text_url) { |media| media.local? ? medium_url(media) : nil }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%p.hint= t('two_factor_auth.recovery_instructions')
|
||||
|
||||
%ol.recovery-codes
|
||||
- @codes.each do |code|
|
||||
- recovery_codes.each do |code|
|
||||
%li
|
||||
%samp= code
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- content_for :page_title do
|
||||
= t('settings.two_factor_auth')
|
||||
|
||||
= render 'recovery_codes'
|
||||
= render partial: 'recovery_codes', object: @codes
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- content_for :page_title do
|
||||
= t('settings.two_factor_auth')
|
||||
|
||||
= render 'recovery_codes'
|
||||
= render partial: 'recovery_codes', object: @codes
|
||||
|
|
4
app/views/stream_entries/_og_description.html.haml
Normal file
4
app/views/stream_entries/_og_description.html.haml
Normal file
|
@ -0,0 +1,4 @@
|
|||
- if activity.is_a?(Status) && activity.spoiler_text?
|
||||
%meta{ property: 'og:description', content: activity.spoiler_text }/
|
||||
- else
|
||||
%meta{ property: 'og:description', content: activity.content }/
|
6
app/views/stream_entries/_og_image.html.haml
Normal file
6
app/views/stream_entries/_og_image.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
|||
- if activity.is_a?(Status) && activity.non_sensitive_with_media?
|
||||
%meta{ property: 'og:image', content: full_asset_url(activity.media_attachments.first.file.url(:small)) }/
|
||||
- else
|
||||
%meta{ property: 'og:image', content: full_asset_url(account.avatar.url(:original)) }/
|
||||
%meta{ property: 'og:image:width', content: '120' }/
|
||||
%meta{ property: 'og:image:height', content: '120' }/
|
|
@ -6,17 +6,8 @@
|
|||
%meta{ property: 'og:type', content: 'article' }/
|
||||
%meta{ property: 'og:title', content: "#{@account.username} on #{Rails.configuration.x.local_domain}" }/
|
||||
|
||||
- if @stream_entry.activity.is_a?(Status) && !@stream_entry.activity.spoiler_text.blank?
|
||||
%meta{ property: 'og:description', content: @stream_entry.activity.spoiler_text }/
|
||||
- else
|
||||
%meta{ property: 'og:description', content: @stream_entry.activity.content }/
|
||||
|
||||
- if @stream_entry.activity.is_a?(Status) && !@stream_entry.activity.sensitive? && @stream_entry.activity.media_attachments.size > 0
|
||||
%meta{ property: 'og:image', content: full_asset_url(@stream_entry.activity.media_attachments.first.file.url(:small)) }/
|
||||
- else
|
||||
%meta{ property: 'og:image', content: full_asset_url(@account.avatar.url(:original)) }/
|
||||
%meta{ property: 'og:image:width', content: '120' }/
|
||||
%meta{ property: 'og:image:height', content: '120' }/
|
||||
= render 'stream_entries/og_description', activity: @stream_entry.activity
|
||||
= render 'stream_entries/og_image', activity: @stream_entry.activity, account: @account
|
||||
|
||||
%meta{ property: 'twitter:card', content: 'summary' }/
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue