This commit is contained in:
		
					parent
					
						
							
								03fb6c16ec
							
						
					
				
			
			
				commit
				
					
						e8875c6046
					
				
			
		
					 15 changed files with 184 additions and 7 deletions
				
			
		|  | @ -11,8 +11,8 @@ class Api::V1::TimelinesController < ApiController | |||
|     @statuses = cache_collection(@statuses) | ||||
| 
 | ||||
|     set_maps(@statuses) | ||||
|     set_counters_maps(@statuses) | ||||
|     set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) | ||||
|     # set_counters_maps(@statuses) | ||||
|     # set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) | ||||
| 
 | ||||
|     next_path = api_v1_home_timeline_url(max_id: @statuses.last.id)    unless @statuses.empty? | ||||
|     prev_path = api_v1_home_timeline_url(since_id: @statuses.first.id) unless @statuses.empty? | ||||
|  | @ -27,8 +27,8 @@ class Api::V1::TimelinesController < ApiController | |||
|     @statuses = cache_collection(@statuses) | ||||
| 
 | ||||
|     set_maps(@statuses) | ||||
|     set_counters_maps(@statuses) | ||||
|     set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) | ||||
|     # set_counters_maps(@statuses) | ||||
|     # set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) | ||||
| 
 | ||||
|     next_path = api_v1_public_timeline_url(max_id: @statuses.last.id)    unless @statuses.empty? | ||||
|     prev_path = api_v1_public_timeline_url(since_id: @statuses.first.id) unless @statuses.empty? | ||||
|  | @ -44,8 +44,8 @@ class Api::V1::TimelinesController < ApiController | |||
|     @statuses = cache_collection(@statuses) | ||||
| 
 | ||||
|     set_maps(@statuses) | ||||
|     set_counters_maps(@statuses) | ||||
|     set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) | ||||
|     # set_counters_maps(@statuses) | ||||
|     # set_account_counters_maps(@statuses.flat_map { |s| [s.account, s.reblog? ? s.reblog.account : nil] }.compact.uniq) | ||||
| 
 | ||||
|     next_path = api_v1_hashtag_timeline_url(params[:id], max_id: @statuses.last.id)    unless @statuses.empty? | ||||
|     prev_path = api_v1_hashtag_timeline_url(params[:id], since_id: @statuses.first.id) unless @statuses.empty? | ||||
|  |  | |||
							
								
								
									
										34
									
								
								app/controllers/settings/imports_controller.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/controllers/settings/imports_controller.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Settings::ImportsController < ApplicationController | ||||
|   layout 'admin' | ||||
| 
 | ||||
|   before_action :authenticate_user! | ||||
|   before_action :set_account | ||||
| 
 | ||||
|   def show | ||||
|     @import = Import.new | ||||
|   end | ||||
| 
 | ||||
|   def create | ||||
|     @import = Import.new(import_params) | ||||
|     @import.account = @account | ||||
| 
 | ||||
|     if @import.save | ||||
|       ImportWorker.perform_async(@import.id) | ||||
|       redirect_to settings_import_path, notice: I18n.t('imports.success') | ||||
|     else | ||||
|       render action: :show | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_account | ||||
|     @account = current_user.account | ||||
|   end | ||||
| 
 | ||||
|   def import_params | ||||
|     params.require(:import).permit(:data, :type) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										14
									
								
								app/models/import.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/models/import.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Import < ApplicationRecord | ||||
|   self.inheritance_column = false | ||||
| 
 | ||||
|   enum type: [:following, :blocking] | ||||
| 
 | ||||
|   belongs_to :account | ||||
| 
 | ||||
|   FILE_TYPES = ['text/plain', 'text/csv'].freeze | ||||
| 
 | ||||
|   has_attached_file :data, url: '/system/:hash.:extension', hash_secret: ENV.fetch('PAPERCLIP_SECRET') | ||||
|   validates_attachment_content_type :data, content_type: FILE_TYPES | ||||
| end | ||||
|  | @ -12,6 +12,15 @@ | |||
|     .content-wrapper | ||||
|       .content | ||||
|         %h2= yield :page_title | ||||
| 
 | ||||
|         - if flash[:notice] | ||||
|           .flash-message.notice | ||||
|             %strong= flash[:notice] | ||||
| 
 | ||||
|         - if flash[:alert] | ||||
|           .flash-message.alert | ||||
|             %strong= flash[:alert] | ||||
| 
 | ||||
|         = yield | ||||
| 
 | ||||
| = render template: "layouts/application", locals: { body_classes: 'admin' } | ||||
|  |  | |||
							
								
								
									
										11
									
								
								app/views/settings/imports/show.html.haml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/views/settings/imports/show.html.haml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| - content_for :page_title do | ||||
|   = t('settings.import') | ||||
| 
 | ||||
| %p.hint= t('imports.preface') | ||||
| 
 | ||||
| = simple_form_for @import, url: settings_import_path do |f| | ||||
|   = f.input :type, collection: Import.types.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| I18n.t("imports.types.#{type}") } | ||||
|   = f.input :data, wrapper: :with_label, hint: t('simple_form.hints.imports.data') | ||||
| 
 | ||||
|   .actions | ||||
|     = f.button :button, t('imports.upload'), type: :submit | ||||
							
								
								
									
										54
									
								
								app/workers/import_worker.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								app/workers/import_worker.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| require 'csv' | ||||
| 
 | ||||
| class ImportWorker | ||||
|   include Sidekiq::Worker | ||||
| 
 | ||||
|   sidekiq_options retry: false | ||||
| 
 | ||||
|   def perform(import_id) | ||||
|     import = Import.find(import_id) | ||||
| 
 | ||||
|     case import.type | ||||
|     when 'blocking' | ||||
|       process_blocks(import) | ||||
|     when 'following' | ||||
|       process_follows(import) | ||||
|     end | ||||
| 
 | ||||
|     import.destroy | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def process_blocks(import) | ||||
|     from_account = import.account | ||||
| 
 | ||||
|     CSV.foreach(import.data.path) do |row| | ||||
|       next if row.size != 1 | ||||
| 
 | ||||
|       begin | ||||
|         target_account = FollowRemoteAccountService.new.call(row[0]) | ||||
|         next if target_account.nil? | ||||
|         BlockService.new.call(from_account, target_account) | ||||
|       rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError | ||||
|         next | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def process_follows(import) | ||||
|     from_account = import.account | ||||
| 
 | ||||
|     CSV.foreach(import.data.path) do |row| | ||||
|       next if row.size != 1 | ||||
| 
 | ||||
|       begin | ||||
|         FollowService.new.call(from_account, row[0]) | ||||
|       rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError | ||||
|         next | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  | @ -85,6 +85,13 @@ en: | |||
|     validation_errors: | ||||
|       one: Something isn't quite right yet! Please review the error below | ||||
|       other: Something isn't quite right yet! Please review %{count} errors below | ||||
|   imports: | ||||
|     preface: You can import certain data like all the people you are following or blocking into your account on this instance, from files created by an export on another instance. | ||||
|     success: Your data was successfully uploaded and will now be processed in due time | ||||
|     types: | ||||
|       blocking: Blocking list | ||||
|       following: Following list | ||||
|     upload: Upload | ||||
|   landing_strip_html: <strong>%{name}</strong> is a user on <strong>%{domain}</strong>. You can follow them or interact with them if you have an account anywhere in the fediverse. If you don't, you can <a href="%{sign_up_path}">sign up here</a>. | ||||
|   notification_mailer: | ||||
|     digest: | ||||
|  | @ -124,6 +131,7 @@ en: | |||
|     back: Back to Mastodon | ||||
|     edit_profile: Edit profile | ||||
|     export: Data export | ||||
|     import: Import | ||||
|     preferences: Preferences | ||||
|     settings: Settings | ||||
|     two_factor_auth: Two-factor Authentication | ||||
|  |  | |||
|  | @ -8,12 +8,15 @@ en: | |||
|         header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px | ||||
|         locked: Requires you to manually approve followers and defaults post privacy to followers-only | ||||
|         note: At most 160 characters | ||||
|       imports: | ||||
|         data: CSV file exported from another Mastodon instance | ||||
|     labels: | ||||
|       defaults: | ||||
|         avatar: Avatar | ||||
|         confirm_new_password: Confirm new password | ||||
|         confirm_password: Confirm password | ||||
|         current_password: Current password | ||||
|         data: Data | ||||
|         display_name: Display name | ||||
|         email: E-mail address | ||||
|         header: Header | ||||
|  | @ -24,6 +27,7 @@ en: | |||
|         otp_attempt: Two-factor code | ||||
|         password: Password | ||||
|         setting_default_privacy: Post privacy | ||||
|         type: Import type | ||||
|         username: Username | ||||
|       interactions: | ||||
|         must_be_follower: Block notifications from non-followers | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ SimpleNavigation::Configuration.run do |navigation| | |||
|       settings.item :preferences, safe_join([fa_icon('sliders fw'), t('settings.preferences')]), settings_preferences_url | ||||
|       settings.item :password, safe_join([fa_icon('cog fw'), t('auth.change_password')]), edit_user_registration_url | ||||
|       settings.item :two_factor_auth, safe_join([fa_icon('mobile fw'), t('settings.two_factor_auth')]), settings_two_factor_auth_url | ||||
|       settings.item :import, safe_join([fa_icon('cloud-upload fw'), t('settings.import')]), settings_import_url | ||||
|       settings.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url | ||||
|       settings.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url | ||||
|     end | ||||
|  |  | |||
|  | @ -51,6 +51,7 @@ Rails.application.routes.draw do | |||
|   namespace :settings do | ||||
|     resource :profile, only: [:show, :update] | ||||
|     resource :preferences, only: [:show, :update] | ||||
|     resource :import, only: [:show, :create] | ||||
| 
 | ||||
|     resource :export, only: [:show] do | ||||
|       collection do | ||||
|  |  | |||
							
								
								
									
										11
									
								
								db/migrate/20170330163835_create_imports.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								db/migrate/20170330163835_create_imports.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| class CreateImports < ActiveRecord::Migration[5.0] | ||||
|   def change | ||||
|     create_table :imports do |t| | ||||
|       t.integer :account_id, null: false | ||||
|       t.integer :type, null: false | ||||
|       t.boolean :approved | ||||
| 
 | ||||
|       t.timestamps | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										11
									
								
								db/migrate/20170330164118_add_attachment_data_to_imports.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								db/migrate/20170330164118_add_attachment_data_to_imports.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| class AddAttachmentDataToImports < ActiveRecord::Migration | ||||
|   def self.up | ||||
|     change_table :imports do |t| | ||||
|       t.attachment :data | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def self.down | ||||
|     remove_attachment :imports, :data | ||||
|   end | ||||
| end | ||||
							
								
								
									
										14
									
								
								db/schema.rb
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								db/schema.rb
									
										
									
									
									
								
							|  | @ -10,7 +10,7 @@ | |||
| # | ||||
| # It's strongly recommended that you check this file into your version control system. | ||||
| 
 | ||||
| ActiveRecord::Schema.define(version: 20170330021336) do | ||||
| ActiveRecord::Schema.define(version: 20170330164118) do | ||||
| 
 | ||||
|   # These are extensions that must be enabled in order to support this database | ||||
|   enable_extension "plpgsql" | ||||
|  | @ -93,6 +93,18 @@ ActiveRecord::Schema.define(version: 20170330021336) do | |||
|     t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true, using: :btree | ||||
|   end | ||||
| 
 | ||||
|   create_table "imports", force: :cascade do |t| | ||||
|     t.integer  "account_id",        null: false | ||||
|     t.integer  "type",              null: false | ||||
|     t.boolean  "approved" | ||||
|     t.datetime "created_at",        null: false | ||||
|     t.datetime "updated_at",        null: false | ||||
|     t.string   "data_file_name" | ||||
|     t.string   "data_content_type" | ||||
|     t.integer  "data_file_size" | ||||
|     t.datetime "data_updated_at" | ||||
|   end | ||||
| 
 | ||||
|   create_table "media_attachments", force: :cascade do |t| | ||||
|     t.bigint   "status_id" | ||||
|     t.string   "file_file_name" | ||||
|  |  | |||
							
								
								
									
										2
									
								
								spec/fabricators/import_fabricator.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								spec/fabricators/import_fabricator.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| Fabricator(:import) do | ||||
| end | ||||
							
								
								
									
										5
									
								
								spec/models/import_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								spec/models/import_spec.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| require 'rails_helper' | ||||
| 
 | ||||
| RSpec.describe Import, type: :model do | ||||
| 
 | ||||
| end | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue