Merge branch 'kb_development' into kb_migration
This commit is contained in:
commit
ce5a9f2500
9 changed files with 50 additions and 27 deletions
|
@ -31,6 +31,7 @@ class Api::V1::ListsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
raise Mastodon::ValidationError, I18n.t('antennas.errors.remove_list_with_antenna') if Antenna.where(list_id: @list.id).any?
|
||||||
@list.destroy!
|
@list.destroy!
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,6 +17,7 @@ const messages = defineMessages({
|
||||||
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
||||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||||
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
|
||||||
|
antennas: { id: 'navigation_bar.antennas', defaultMessage: 'Antennas' },
|
||||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||||
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
|
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
|
||||||
});
|
});
|
||||||
|
@ -53,6 +54,7 @@ class ActionBar extends React.PureComponent {
|
||||||
menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
|
menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
|
||||||
menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' });
|
menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' });
|
||||||
menu.push({ text: intl.formatMessage(messages.filters), href: '/filters' });
|
menu.push({ text: intl.formatMessage(messages.filters), href: '/filters' });
|
||||||
|
menu.push({ text: intl.formatMessage(messages.antennas), href: '/antennas' });
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
menu.push({ text: intl.formatMessage(messages.logout), action: this.handleLogout });
|
menu.push({ text: intl.formatMessage(messages.logout), action: this.handleLogout });
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
# min_reblogs :integer
|
# min_reblogs :integer
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
|
# min_emojis :integer
|
||||||
|
# keep_self_emoji :boolean default(TRUE), not null
|
||||||
#
|
#
|
||||||
class AccountStatusesCleanupPolicy < ApplicationRecord
|
class AccountStatusesCleanupPolicy < ApplicationRecord
|
||||||
include Redisable
|
include Redisable
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# expires_at :datetime
|
# expires_at :datetime
|
||||||
# with_media_only :boolean default(FALSE), not null
|
# with_media_only :boolean default(FALSE), not null
|
||||||
|
# exclude_domains :jsonb
|
||||||
|
# exclude_accounts :jsonb
|
||||||
|
# exclude_tags :jsonb
|
||||||
#
|
#
|
||||||
class Antenna < ApplicationRecord
|
class Antenna < ApplicationRecord
|
||||||
include Expireable
|
include Expireable
|
||||||
|
@ -86,7 +89,7 @@ class Antenna < ApplicationRecord
|
||||||
def keywords_raw=(raw)
|
def keywords_raw=(raw)
|
||||||
keywords = raw.split(/\R/).filter { |r| r.present? && r.length >= 2 }.uniq
|
keywords = raw.split(/\R/).filter { |r| r.present? && r.length >= 2 }.uniq
|
||||||
self[:keywords] = keywords
|
self[:keywords] = keywords
|
||||||
self[:any_keywords] = !keywords.any? && !exclude_keywords&.any?
|
self[:any_keywords] = !keywords.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_keywords_raw
|
def exclude_keywords_raw
|
||||||
|
@ -98,7 +101,6 @@ class Antenna < ApplicationRecord
|
||||||
def exclude_keywords_raw=(raw)
|
def exclude_keywords_raw=(raw)
|
||||||
exclude_keywords = raw.split(/\R/).filter { |r| r.present? }.uniq
|
exclude_keywords = raw.split(/\R/).filter { |r| r.present? }.uniq
|
||||||
self[:exclude_keywords] = exclude_keywords
|
self[:exclude_keywords] = exclude_keywords
|
||||||
self[:any_keywords] = !keywords&.any? && !exclude_keywords.any?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def tags_raw
|
def tags_raw
|
||||||
|
@ -118,18 +120,19 @@ class Antenna < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_tags_raw
|
def exclude_tags_raw
|
||||||
antenna_tags.where(exclude: true).map(&:tag).map(&:name).join("\n")
|
return '' if !exclude_tags.present?
|
||||||
|
Tag.where(id: exclude_tags).map(&:name).join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_tags_raw=(raw)
|
def exclude_tags_raw=(raw)
|
||||||
return if exclude_tags_raw == raw
|
return if exclude_tags_raw == raw
|
||||||
|
|
||||||
|
tags = []
|
||||||
tag_names = raw.split(/\R/).filter { |r| r.present? }.map { |r| r.start_with?('#') ? r[1..-1] : r }.uniq
|
tag_names = raw.split(/\R/).filter { |r| r.present? }.map { |r| r.start_with?('#') ? r[1..-1] : r }.uniq
|
||||||
|
|
||||||
antenna_tags.where(exclude: true).destroy_all
|
|
||||||
Tag.find_or_create_by_names(tag_names).each do |tag|
|
Tag.find_or_create_by_names(tag_names).each do |tag|
|
||||||
antenna_tags.create!(tag: tag, exclude: true)
|
tags << tag.id
|
||||||
end
|
end
|
||||||
|
self[:exclude_tags] = tags
|
||||||
end
|
end
|
||||||
|
|
||||||
def domains_raw
|
def domains_raw
|
||||||
|
@ -149,18 +152,15 @@ class Antenna < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_domains_raw
|
def exclude_domains_raw
|
||||||
antenna_domains.where(exclude: true).map(&:name).join("\n")
|
return '' if !exclude_domains.present?
|
||||||
|
exclude_domains.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_domains_raw=(raw)
|
def exclude_domains_raw=(raw)
|
||||||
return if exclude_domains_raw == raw
|
return if exclude_domains_raw == raw
|
||||||
|
|
||||||
domain_names = raw.split(/\R/).filter { |r| r.present? }.uniq
|
domain_names = raw.split(/\R/).filter { |r| r.present? }.uniq
|
||||||
|
self[:exclude_domains] = domain_names
|
||||||
antenna_domains.where(exclude: true).destroy_all
|
|
||||||
domain_names.each do |domain|
|
|
||||||
antenna_domains.create!(name: domain, exclude: true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def accounts_raw
|
def accounts_raw
|
||||||
|
@ -186,7 +186,8 @@ class Antenna < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_accounts_raw
|
def exclude_accounts_raw
|
||||||
antenna_accounts.where(exclude: true).map(&:account).map { |account| account.domain ? "@#{account.username}@#{account.domain}" : "@#{account.username}" }.join("\n")
|
return '' if !exclude_accounts.present?
|
||||||
|
Account.where(id: exclude_accounts).map { |account| account.domain ? "@#{account.username}@#{account.domain}" : "@#{account.username}" }.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def exclude_accounts_raw=(raw)
|
def exclude_accounts_raw=(raw)
|
||||||
|
@ -194,16 +195,15 @@ class Antenna < ApplicationRecord
|
||||||
|
|
||||||
account_names = raw.split(/\R/).filter { |r| r.present? }.map { |r| r.start_with?('@') ? r[1..-1] : r }.uniq
|
account_names = raw.split(/\R/).filter { |r| r.present? }.map { |r| r.start_with?('@') ? r[1..-1] : r }.uniq
|
||||||
|
|
||||||
hit = false
|
accounts = []
|
||||||
antenna_accounts.where(exclude: true).destroy_all
|
|
||||||
account_names.each do |name|
|
account_names.each do |name|
|
||||||
username, domain = name.split('@')
|
username, domain = name.split('@')
|
||||||
account = Account.find_by(username: username, domain: domain)
|
account = Account.find_by(username: username, domain: domain)
|
||||||
if account.present?
|
if account.present?
|
||||||
antenna_accounts.create!(account: account, exclude: true)
|
accounts << account.id
|
||||||
hit = true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
self[:exclude_accounts] = accounts
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -118,30 +118,34 @@ class FanOutOnWriteService < BaseService
|
||||||
|
|
||||||
def deliver_to_antennas!
|
def deliver_to_antennas!
|
||||||
lists = []
|
lists = []
|
||||||
|
tag_ids = @status.tags.pluck(:id)
|
||||||
|
domain = @account.domain || Rails.configuration.x.local_domain
|
||||||
|
|
||||||
antennas = Antenna.availables
|
antennas = Antenna.availables
|
||||||
antennas = antennas.left_joins(:antenna_accounts).where(any_accounts: true).or(Antenna.availables.left_joins(:antenna_accounts) .where(antenna_accounts: { exclude: false, account: @status.account }))
|
antennas = antennas.left_joins(:antenna_accounts).where(any_accounts: true).or(Antenna.availables.left_joins(:antenna_accounts) .where(antenna_accounts: { exclude: false, account: @status.account }))
|
||||||
antennas = antennas.left_joins(:antenna_domains) .where(any_domains: true) .or(Antenna.availables.left_joins(:antenna_accounts).left_joins(:antenna_domains) .where(antenna_domains: { exclude: false, name: @status.account.domain }))
|
antennas = antennas.left_joins(:antenna_domains) .where(any_domains: true) .or(Antenna.availables.left_joins(:antenna_accounts).left_joins(:antenna_domains) .where(antenna_domains: { exclude: false, name: @status.account.domain }))
|
||||||
antennas = antennas.left_joins(:antenna_tags) .where(any_tags: true) .or(Antenna.availables.left_joins(:antenna_accounts).left_joins(:antenna_domains).left_joins(:antenna_tags).where(antenna_tags: { exclude: false, tag: @status.tags }))
|
antennas = antennas.left_joins(:antenna_tags) .where(any_tags: true) .or(Antenna.availables.left_joins(:antenna_accounts).left_joins(:antenna_domains).left_joins(:antenna_tags).where(antenna_tags: { exclude: false, tag: @status.tags }))
|
||||||
antennas = antennas.where(account: @status.account.followers) if @status.visibility.to_sym == :unlisted
|
antennas = antennas.where(account: @status.account.followers) if @status.visibility.to_sym == :unlisted
|
||||||
antennas = antennas.where(with_media_only: false) if !@status.with_media?
|
antennas = antennas.where(with_media_only: false) if !@status.with_media?
|
||||||
|
antennas = antennas.where.not(account: @status.account.blocking)
|
||||||
|
antennas = antennas.includes(:antenna_accounts).includes(:antenna_domains).includes(:antenna_tags)
|
||||||
antennas.in_batches do |ans|
|
antennas.in_batches do |ans|
|
||||||
ans.each do |antenna|
|
ans.each do |antenna|
|
||||||
next if !antenna.enabled?
|
next if !antenna.enabled?
|
||||||
next if @status.account.blocking?(antenna.account)
|
|
||||||
next if antenna.keywords.any? && !([nil, :public].include?(@status.searchability&.to_sym))
|
next if antenna.keywords.any? && !([nil, :public].include?(@status.searchability&.to_sym))
|
||||||
next if antenna.keywords.any? && !antenna.keywords.any? { |keyword| @status.text.include?(keyword) }
|
next if antenna.keywords.any? && !antenna.keywords.any? { |keyword| @status.text.include?(keyword) }
|
||||||
next if antenna.exclude_keywords.any? && antenna.exclude_keywords.any? { |keyword| @status.text.include?(keyword) }
|
next if antenna.exclude_keywords&.any? { |keyword| @status.text.include?(keyword) }
|
||||||
next if antenna.antenna_accounts.where(exclude: true, account: @status.account).any?
|
next if antenna.exclude_accounts&.include?(@status.account_id)
|
||||||
next if antenna.antenna_domains.where(exclude: true, name: @status.account.domain).any?
|
next if antenna.exclude_domains&.include?(domain)
|
||||||
next if antenna.antenna_tags.where(exclude: true, tag: @status.tags).any?
|
next if antenna.exclude_tags&.any? { |tag_id| tag_ids.include?(tag_id) }
|
||||||
lists << antenna.list
|
lists << antenna.list_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
lists = lists.uniq
|
lists = lists.uniq
|
||||||
|
|
||||||
if lists.any?
|
if lists.any?
|
||||||
FeedInsertWorker.push_bulk(lists) do |list|
|
FeedInsertWorker.push_bulk(lists) do |list|
|
||||||
[@status.id, list.id, 'list', { 'update' => update? }]
|
[@status.id, list, 'list', { 'update' => update? }]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -994,6 +994,7 @@ en:
|
||||||
empty_contexts: No contexts! You must set any context filters
|
empty_contexts: No contexts! You must set any context filters
|
||||||
invalid_context: None or invalid context supplied
|
invalid_context: None or invalid context supplied
|
||||||
invalid_list_owner: This list is not yours
|
invalid_list_owner: This list is not yours
|
||||||
|
remove_list_with_antenna: Cannot remove list because this list is related to antenna.
|
||||||
index:
|
index:
|
||||||
contexts: Antennas in %{contexts}
|
contexts: Antennas in %{contexts}
|
||||||
delete: Delete
|
delete: Delete
|
||||||
|
|
|
@ -945,7 +945,7 @@ ja:
|
||||||
hint_html: 他のアカウントからこのアカウントにフォロワーを引き継いで引っ越したい場合、ここでエイリアスを作成しておく必要があります。エイリアス自体は<strong>無害で、取り消す</strong>ことができます。<strong>引っ越しは以前のアカウント側から開始する必要があります</strong>。
|
hint_html: 他のアカウントからこのアカウントにフォロワーを引き継いで引っ越したい場合、ここでエイリアスを作成しておく必要があります。エイリアス自体は<strong>無害で、取り消す</strong>ことができます。<strong>引っ越しは以前のアカウント側から開始する必要があります</strong>。
|
||||||
remove: エイリアスを削除
|
remove: エイリアスを削除
|
||||||
antennas:
|
antennas:
|
||||||
beta: アンテナ機能はベータ版です。今後、予告なく全データリセット・機能削除を行う場合があります。この機能の存在は外部に積極的に宣伝しないよう、ご協力をお願いします。
|
beta: アンテナ機能はベータ版です。今後、予告なく全データリセット・機能削除を行う場合があります。
|
||||||
contexts:
|
contexts:
|
||||||
account: アカウント
|
account: アカウント
|
||||||
domain: ドメイン
|
domain: ドメイン
|
||||||
|
@ -954,12 +954,13 @@ ja:
|
||||||
errors:
|
errors:
|
||||||
empty_contexts: 絞り込み条件が1つも指定されていないため無効です(除外条件はカウントされません)
|
empty_contexts: 絞り込み条件が1つも指定されていないため無効です(除外条件はカウントされません)
|
||||||
invalid_list_owner: これはあなたのリストではありません
|
invalid_list_owner: これはあなたのリストではありません
|
||||||
|
remove_list_with_antenna: アンテナが関連付けられているリストは削除できません
|
||||||
edit:
|
edit:
|
||||||
accounts_hint: ローカルアカウントの場合は「@info」、リモートアカウントの場合は「@info@example.com」の形式で指定します。サーバーが認識していないアカウントは保存時に自動的に削除されます。
|
accounts_hint: ローカルアカウントの場合は「@info」、リモートアカウントの場合は「@info@example.com」の形式で指定します。サーバーが認識していないアカウントは保存時に自動的に削除されます。
|
||||||
accounts_raw: 絞り込むアカウント
|
accounts_raw: 絞り込むアカウント
|
||||||
available: 有効
|
available: 有効
|
||||||
description: アンテナは、サーバーが認識した全ての公開・ローカル公開投稿のうち、検索許可が「公開」または明示的に設定されていないもの(検索許可システムに対応していないサーバーからの投稿)、かつ購読を拒否していないすべてのアカウントからの投稿が対象です。検出された投稿は、指定したリストに追加されます。
|
description: アンテナは、サーバーが認識した全ての公開・ローカル公開投稿のうち、検索許可が「公開」または明示的に設定されていないもの(検索許可システムに対応していないサーバーからの投稿)、かつ購読を拒否していないすべてのアカウントからの投稿が対象です。検出された投稿は、指定したリストに追加されます。
|
||||||
domains_hint: ドメインとは、アカウントIDやサイトのURLのうち「kmy.blue」「example.com」に該当する部分です。自身のサーバーを指定することはできません
|
domains_hint: ドメインとは、アカウントIDやサイトのURLのうち「kmy.blue」「example.com」に該当する部分です
|
||||||
domains_raw: 絞り込むドメイン
|
domains_raw: 絞り込むドメイン
|
||||||
exclude_accounts_raw: 除外するアカウント
|
exclude_accounts_raw: 除外するアカウント
|
||||||
exclude_domains_raw: 除外するドメイン
|
exclude_domains_raw: 除外するドメイン
|
||||||
|
|
7
db/migrate/20230426013738_add_excludes_to_antennas.rb
Normal file
7
db/migrate/20230426013738_add_excludes_to_antennas.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class AddExcludesToAntennas < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
add_column :antennas, :exclude_domains, :jsonb
|
||||||
|
add_column :antennas, :exclude_accounts, :jsonb
|
||||||
|
add_column :antennas, :exclude_tags, :jsonb
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2023_04_23_233429) do
|
ActiveRecord::Schema.define(version: 2023_04_26_013738) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -117,6 +117,8 @@ ActiveRecord::Schema.define(version: 2023_04_23_233429) do
|
||||||
t.integer "min_reblogs"
|
t.integer "min_reblogs"
|
||||||
t.datetime "created_at", precision: 6, null: false
|
t.datetime "created_at", precision: 6, null: false
|
||||||
t.datetime "updated_at", precision: 6, null: false
|
t.datetime "updated_at", precision: 6, null: false
|
||||||
|
t.integer "min_emojis"
|
||||||
|
t.boolean "keep_self_emoji", default: true, null: false
|
||||||
t.index ["account_id"], name: "index_account_statuses_cleanup_policies_on_account_id"
|
t.index ["account_id"], name: "index_account_statuses_cleanup_policies_on_account_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -300,6 +302,9 @@ ActiveRecord::Schema.define(version: 2023_04_23_233429) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.datetime "expires_at"
|
t.datetime "expires_at"
|
||||||
t.boolean "with_media_only", default: false, null: false
|
t.boolean "with_media_only", default: false, null: false
|
||||||
|
t.jsonb "exclude_domains"
|
||||||
|
t.jsonb "exclude_accounts"
|
||||||
|
t.jsonb "exclude_tags"
|
||||||
t.index ["account_id"], name: "index_antennas_on_account_id"
|
t.index ["account_id"], name: "index_antennas_on_account_id"
|
||||||
t.index ["any_accounts"], name: "index_antennas_on_any_accounts"
|
t.index ["any_accounts"], name: "index_antennas_on_any_accounts"
|
||||||
t.index ["any_domains"], name: "index_antennas_on_any_domains"
|
t.index ["any_domains"], name: "index_antennas_on_any_domains"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue