diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb
index be1699315f6..eee4cc7feb5 100644
--- a/app/controllers/settings/imports_controller.rb
+++ b/app/controllers/settings/imports_controller.rb
@@ -13,6 +13,7 @@ class Settings::ImportsController < Settings::BaseController
domain_blocking: 'blocked_domains_failures.csv',
bookmarks: 'bookmarks_failures.csv',
lists: 'lists_failures.csv',
+ filters: 'filters_failures.csv',
}.freeze
TYPE_TO_HEADERS_MAP = {
@@ -22,6 +23,7 @@ class Settings::ImportsController < Settings::BaseController
domain_blocking: false,
bookmarks: false,
lists: false,
+ filters: false,
}.freeze
RECENT_IMPORTS_LIMIT = 10
diff --git a/app/models/bulk_import.rb b/app/models/bulk_import.rb
index e3e46d7b1c6..9b873155616 100644
--- a/app/models/bulk_import.rb
+++ b/app/models/bulk_import.rb
@@ -34,6 +34,7 @@ class BulkImport < ApplicationRecord
domain_blocking: 3,
bookmarks: 4,
lists: 5,
+ filters: 6,
}
enum :state, {
diff --git a/app/models/form/import.rb b/app/models/form/import.rb
index 3cc4af064ff..f5c812be587 100644
--- a/app/models/form/import.rb
+++ b/app/models/form/import.rb
@@ -19,6 +19,7 @@ class Form::Import
domain_blocking: ['#domain'],
bookmarks: ['#uri'],
lists: ['List name', 'Account address'],
+ filters: ['Title', 'Context', 'Keywords', 'Action', 'Expire after'],
}.freeze
KNOWN_FIRST_HEADERS = EXPECTED_HEADERS_BY_TYPE.values.map(&:first).uniq.freeze
@@ -55,6 +56,8 @@ class Form::Import
:bookmarks
elsif file_name_matches?('lists')
:lists
+ elsif file_name_matches?('filters') || csv_headers_match?('Keywords')
+ :filters
end
end
@@ -102,6 +105,8 @@ class Form::Import
['#uri']
when :lists
['List name', 'Account address']
+ when :filters
+ ['Title', 'Context', 'Keywords', 'Action', 'Expire after']
end
end
@@ -109,19 +114,30 @@ class Form::Import
return @csv_data if defined?(@csv_data)
csv_converter = lambda do |field, field_info|
- case field_info.header
- when 'Show boosts', 'Notify on new posts', 'Hide notifications'
- ActiveModel::Type::Boolean.new.cast(field&.downcase)
- when 'Languages'
- field&.split(',')&.map(&:strip)&.presence
- when 'Account address'
- field.strip.gsub(/\A@/, '')
- when '#domain'
- field&.strip&.downcase
- when '#uri', 'List name'
- field.strip
+ if :type == :filters
+ case field_info.header
+ when 'Context', 'Keywords'
+ field&.split(',')&.map(&:strip)&.presence
+ when 'Expire after'
+ field.blank? ? nil : Time.zone.parse(field)
+ else
+ field
+ end
else
- field
+ case field_info.header
+ when 'Show boosts', 'Notify on new posts', 'Hide notifications'
+ ActiveModel::Type::Boolean.new.cast(field&.downcase)
+ when 'Languages'
+ field&.split(',')&.map(&:strip)&.presence
+ when 'Account address'
+ field.strip.gsub(/\A@/, '')
+ when '#domain'
+ field&.strip&.downcase
+ when '#uri', 'List name'
+ field.strip
+ else
+ field
+ end
end
end
diff --git a/app/services/bulk_import_service.rb b/app/services/bulk_import_service.rb
index a361c7a3dac..471c3f94caf 100644
--- a/app/services/bulk_import_service.rb
+++ b/app/services/bulk_import_service.rb
@@ -18,6 +18,10 @@ class BulkImportService < BaseService
import_bookmarks!
when :lists
import_lists!
+ when :filters
+ import_filters!
+ else
+ raise NotImplementedError, "Unknown import type: #{@import.type}"
end
@import.update!(state: :finished, finished_at: Time.now.utc) if @import.processed_items == @import.total_items
@@ -182,4 +186,14 @@ class BulkImportService < BaseService
[row.id]
end
end
+
+ def import_filters!
+ rows = @import.rows.to_a
+
+ @account.custom_filters.destroy_all if @import.overwrite?
+
+ Import::RowWorker.push_bulk(rows) do |row|
+ [row.id]
+ end
+ end
end
diff --git a/app/views/settings/imports/index.html.haml b/app/views/settings/imports/index.html.haml
index 55421991e13..ec07180326f 100644
--- a/app/views/settings/imports/index.html.haml
+++ b/app/views/settings/imports/index.html.haml
@@ -5,7 +5,7 @@
.field-group
= f.input :type,
as: :grouped_select,
- collection: { constructive: %i(following bookmarks lists), destructive: %i(muting blocking domain_blocking) },
+ collection: { constructive: %i(following bookmarks lists), destructive: %i(filters muting blocking domain_blocking) },
group_label_method: ->(group) { I18n.t("imports.type_groups.#{group.first}") },
group_method: :last,
hint: t('imports.preface'),
diff --git a/config/locales/en.yml b/config/locales/en.yml
index aa0070cff50..5f3ceaa33c6 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1517,6 +1517,9 @@ en:
muting_html:
one: You are about to replace your list of muted account with up to %{count} account from %{filename}.
other: You are about to replace your list of muted accounts with up to %{count} accounts from %{filename}.
+ filters_html:
+ one: You are about to replace your filters with up to %{count} filter from %{filename}.
+ other: You are about to replace your filters with up to %{count} filters from %{filename}.
preambles:
blocking_html:
one: You are about to block up to %{count} account from %{filename}.
@@ -1536,6 +1539,9 @@ en:
muting_html:
one: You are about to mute up to %{count} account from %{filename}.
other: You are about to mute up to %{count} accounts from %{filename}.
+ filters_html:
+ one: You are about to add up to %{count} filter from %{filename}.
+ other: You are about to add up to %{count} filters from %{filename}.
preface: You can import data that you have exported from another server, such as a list of the people you are following or blocking.
recent_imports: Recent imports
states:
@@ -1564,6 +1570,7 @@ en:
following: Following list
lists: Lists
muting: Muting list
+ filters: Filters
upload: Upload
invites:
delete: Deactivate
diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb
index e9579e90756..16b0f436b36 100644
--- a/spec/models/export_spec.rb
+++ b/spec/models/export_spec.rb
@@ -112,8 +112,9 @@ RSpec.describe Export do
it 'returns a csv of custom filters' do
expect(export)
.to contain_exactly(
- include(/statuses/),
- include(/statuses/)
+ contain_exactly('Title', 'Context', 'Keywords', 'Action', 'Expire after'),
+ include('discourse', 'home,notifications', 'discourse', 'warn', be_blank),
+ include(be_present)
)
end
end