Merge branch 'master' into master
commit
db4a41cf58
Binary file not shown.
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 59 KiB |
|
@ -43,7 +43,7 @@ const GettingStarted = ({ intl, me }) => {
|
||||||
|
|
||||||
<div className='scrollable optionally-scrollable' style={{ display: 'flex', flexDirection: 'column' }}>
|
<div className='scrollable optionally-scrollable' style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<div className='static-content getting-started'>
|
<div className='static-content getting-started'>
|
||||||
<p><FormattedMessage id='getting_started.open_source_notice' defaultMessage='Mastodon is open source software. You can contribute or report issues on github at {github}. {apps}.' values={{ github: <a href="https://github.com/tootsuite/mastodon" target="_blank">tootsuite/mastodon</a>, apps: <a href="https://github.com/tootsuite/mastodon/blob/master/docs/Using-Mastodon/Apps.md" target="_blank"><FormattedMessage id='getting_started.apps' defaultMessage='Various apps are available' /></a> }} /></p>
|
<p><FormattedMessage id='getting_started.open_source_notice' defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.' values={{ github: <a href="https://github.com/tootsuite/mastodon" target="_blank">tootsuite/mastodon</a>, apps: <a href="https://github.com/tootsuite/mastodon/blob/master/docs/Using-Mastodon/Apps.md" target="_blank"><FormattedMessage id='getting_started.apps' defaultMessage='Various apps are available' /></a> }} /></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Column>
|
</Column>
|
||||||
|
|
|
@ -25,7 +25,7 @@ const en = {
|
||||||
"getting_started.heading": "Getting started",
|
"getting_started.heading": "Getting started",
|
||||||
"getting_started.about_addressing": "You can follow people if you know their username and the domain they are on by entering an e-mail-esque address into the search form.",
|
"getting_started.about_addressing": "You can follow people if you know their username and the domain they are on by entering an e-mail-esque address into the search form.",
|
||||||
"getting_started.about_shortcuts": "If the target user is on the same domain as you, just the username will work. The same rule applies to mentioning people in statuses.",
|
"getting_started.about_shortcuts": "If the target user is on the same domain as you, just the username will work. The same rule applies to mentioning people in statuses.",
|
||||||
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on github at {github}. {apps}.",
|
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.",
|
||||||
"column.home": "Home",
|
"column.home": "Home",
|
||||||
"column.community": "Local timeline",
|
"column.community": "Local timeline",
|
||||||
"column.public": "Federated timeline",
|
"column.public": "Federated timeline",
|
||||||
|
|
|
@ -9,6 +9,24 @@ class Admin::DomainBlocksController < ApplicationController
|
||||||
@blocks = DomainBlock.paginate(page: params[:page], per_page: 40)
|
@blocks = DomainBlock.paginate(page: params[:page], per_page: 40)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@domain_block = DomainBlock.new
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
@domain_block = DomainBlock.new(resource_params)
|
||||||
|
|
||||||
|
if @domain_block.save
|
||||||
|
DomainBlockWorker.perform_async(@domain_block.id)
|
||||||
|
redirect_to admin_domain_blocks_path, notice: 'Domain block is now being processed'
|
||||||
|
else
|
||||||
|
render action: :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def resource_params
|
||||||
|
params.require(:domain_block).permit(:domain, :severity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,19 +16,19 @@ class Admin::ReportsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve
|
def resolve
|
||||||
@report.update(action_taken: true)
|
@report.update(action_taken: true, action_taken_by_account_id: current_account.id)
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
||||||
def suspend
|
def suspend
|
||||||
Admin::SuspensionWorker.perform_async(@report.target_account.id)
|
Admin::SuspensionWorker.perform_async(@report.target_account.id)
|
||||||
@report.update(action_taken: true)
|
Report.unresolved.where(target_account: @report.target_account).update_all(action_taken: true, action_taken_by_account_id: current_account.id)
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
||||||
def silence
|
def silence
|
||||||
@report.target_account.update(silenced: true)
|
@report.target_account.update(silenced: true)
|
||||||
@report.update(action_taken: true)
|
Report.unresolved.where(target_account: @report.target_account).update_all(action_taken: true, action_taken_by_account_id: current_account.id)
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,12 @@ class Api::V1::AppsController < ApiController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@app = Doorkeeper::Application.create!(name: params[:client_name], redirect_uri: params[:redirect_uris], scopes: (params[:scopes] || Doorkeeper.configuration.default_scopes), website: params[:website])
|
@app = Doorkeeper::Application.create!(name: app_params[:client_name], redirect_uri: app_params[:redirect_uris], scopes: (app_params[:scopes] || Doorkeeper.configuration.default_scopes), website: app_params[:website])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def app_params
|
||||||
|
params.permit(:client_name, :redirect_uris, :scopes, :website)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Api::V1::FollowsController < ApiController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def create
|
def create
|
||||||
raise ActiveRecord::RecordNotFound if params[:uri].blank?
|
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
|
||||||
|
|
||||||
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
|
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
|
||||||
render action: :show
|
render action: :show
|
||||||
|
@ -16,6 +16,10 @@ class Api::V1::FollowsController < ApiController
|
||||||
private
|
private
|
||||||
|
|
||||||
def target_uri
|
def target_uri
|
||||||
params[:uri].strip.gsub(/\A@/, '')
|
follow_params[:uri].strip.gsub(/\A@/, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def follow_params
|
||||||
|
params.permit(:uri)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,10 +10,16 @@ class Api::V1::MediaController < ApiController
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@media = MediaAttachment.create!(account: current_user.account, file: params[:file])
|
@media = MediaAttachment.create!(account: current_user.account, file: media_params[:file])
|
||||||
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
||||||
render json: { error: 'File type of uploaded media could not be verified' }, status: 422
|
render json: { error: 'File type of uploaded media could not be verified' }, status: 422
|
||||||
rescue Paperclip::Error
|
rescue Paperclip::Error
|
||||||
render json: { error: 'Error processing thumbnail for uploaded media' }, status: 500
|
render json: { error: 'Error processing thumbnail for uploaded media' }, status: 500
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def media_params
|
||||||
|
params.permit(:file)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,13 +12,19 @@ class Api::V1::ReportsController < ApiController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
status_ids = params[:status_ids].is_a?(Enumerable) ? params[:status_ids] : [params[:status_ids]]
|
status_ids = report_params[:status_ids].is_a?(Enumerable) ? report_params[:status_ids] : [report_params[:status_ids]]
|
||||||
|
|
||||||
@report = Report.create!(account: current_account,
|
@report = Report.create!(account: current_account,
|
||||||
target_account: Account.find(params[:account_id]),
|
target_account: Account.find(report_params[:account_id]),
|
||||||
status_ids: Status.find(status_ids).pluck(:id),
|
status_ids: Status.find(status_ids).pluck(:id),
|
||||||
comment: params[:comment])
|
comment: report_params[:comment])
|
||||||
|
|
||||||
render :show
|
render :show
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def report_params
|
||||||
|
params.permit(:account_id, :comment, status_ids: [])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -62,11 +62,11 @@ class Api::V1::StatusesController < ApiController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), media_ids: params[:media_ids],
|
@status = PostStatusService.new.call(current_user.account, status_params[:status], status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]), media_ids: status_params[:media_ids],
|
||||||
sensitive: params[:sensitive],
|
sensitive: status_params[:sensitive],
|
||||||
spoiler_text: params[:spoiler_text],
|
spoiler_text: status_params[:spoiler_text],
|
||||||
visibility: params[:visibility],
|
visibility: status_params[:visibility],
|
||||||
application: doorkeeper_token.application)
|
application: doorkeeper_token.application)
|
||||||
render action: :show
|
render action: :show
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -111,4 +111,8 @@ class Api::V1::StatusesController < ApiController
|
||||||
@status = Status.find(params[:id])
|
@status = Status.find(params[:id])
|
||||||
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
|
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def status_params
|
||||||
|
params.permit(:status, :in_reply_to_id, :sensitive, :spoiler_text, :visibility, media_ids: [])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,7 +39,14 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_user_activity
|
def set_user_activity
|
||||||
current_user.touch(:current_sign_in_at) if !current_user.nil? && (current_user.current_sign_in_at.nil? || current_user.current_sign_in_at < 24.hours.ago)
|
return unless !current_user.nil? && (current_user.current_sign_in_at.nil? || current_user.current_sign_in_at < 24.hours.ago)
|
||||||
|
|
||||||
|
# Mark user as signed-in today
|
||||||
|
current_user.update_tracked_fields(request)
|
||||||
|
|
||||||
|
# If the sign in is after a two week break, we need to regenerate their feed
|
||||||
|
RegenerationWorker.perform_async(current_user.account_id) if current_user.last_sign_in_at < 14.days.ago
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_suspension
|
def check_suspension
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
||||||
skip_before_action :authenticate_resource_owner!
|
skip_before_action :authenticate_resource_owner!
|
||||||
|
|
||||||
|
before_action :set_locale
|
||||||
before_action :store_current_location
|
before_action :store_current_location
|
||||||
before_action :authenticate_resource_owner!
|
before_action :authenticate_resource_owner!
|
||||||
|
|
||||||
|
@ -11,4 +12,10 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
||||||
def store_current_location
|
def store_current_location
|
||||||
store_location_for(:user, request.url)
|
store_location_for(:user, request.url)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_locale
|
||||||
|
I18n.locale = current_user.try(:locale) || I18n.default_locale
|
||||||
|
rescue I18n::InvalidLocale
|
||||||
|
I18n.locale = I18n.default_locale
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,4 +4,5 @@ module Mastodon
|
||||||
class Error < StandardError; end
|
class Error < StandardError; end
|
||||||
class NotPermittedError < Error; end
|
class NotPermittedError < Error; end
|
||||||
class ValidationError < Error; end
|
class ValidationError < Error; end
|
||||||
|
class RaceConditionError < Error; end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,17 +10,9 @@ class Feed
|
||||||
max_id = '+inf' if max_id.blank?
|
max_id = '+inf' if max_id.blank?
|
||||||
since_id = '-inf' if since_id.blank?
|
since_id = '-inf' if since_id.blank?
|
||||||
unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", "(#{since_id}", limit: [0, limit], with_scores: true).map(&:last).map(&:to_i)
|
unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", "(#{since_id}", limit: [0, limit], with_scores: true).map(&:last).map(&:to_i)
|
||||||
|
status_map = Status.where(id: unhydrated).cache_ids.map { |s| [s.id, s] }.to_h
|
||||||
|
|
||||||
# If we're after most recent items and none are there, we need to precompute the feed
|
unhydrated.map { |id| status_map[id] }.compact
|
||||||
if unhydrated.empty? && max_id == '+inf' && since_id == '-inf'
|
|
||||||
RegenerationWorker.perform_async(@account.id, @type)
|
|
||||||
@statuses = Status.send("as_#{@type}_timeline", @account).cache_ids.paginate_by_max_id(limit, nil, nil)
|
|
||||||
else
|
|
||||||
status_map = Status.where(id: unhydrated).cache_ids.map { |s| [s.id, s] }.to_h
|
|
||||||
@statuses = unhydrated.map { |id| status_map[id] }.compact
|
|
||||||
end
|
|
||||||
|
|
||||||
@statuses
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
class Report < ApplicationRecord
|
class Report < ApplicationRecord
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
belongs_to :target_account, class_name: 'Account'
|
belongs_to :target_account, class_name: 'Account'
|
||||||
|
belongs_to :action_taken_by_account, class_name: 'Account'
|
||||||
|
|
||||||
scope :unresolved, -> { where(action_taken: false) }
|
scope :unresolved, -> { where(action_taken: false) }
|
||||||
scope :resolved, -> { where(action_taken: true) }
|
scope :resolved, -> { where(action_taken: true) }
|
||||||
|
|
|
@ -188,7 +188,7 @@ class Status < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
before_validation do
|
before_validation do
|
||||||
text.strip!
|
text&.strip!
|
||||||
spoiler_text&.strip!
|
spoiler_text&.strip!
|
||||||
|
|
||||||
self.reply = !(in_reply_to_id.nil? && thread.nil?) unless reply
|
self.reply = !(in_reply_to_id.nil? && thread.nil?) unless reply
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class BlockDomainService < BaseService
|
class BlockDomainService < BaseService
|
||||||
def call(domain, severity)
|
def call(domain_block)
|
||||||
DomainBlock.where(domain: domain).first_or_create!(domain: domain, severity: severity)
|
if domain_block.silence?
|
||||||
|
Account.where(domain: domain_block.domain).update_all(silenced: true)
|
||||||
if severity == :silence
|
|
||||||
Account.where(domain: domain).update_all(silenced: true)
|
|
||||||
else
|
else
|
||||||
Account.where(domain: domain).find_each do |account|
|
Account.where(domain: domain_block.domain).find_each do |account|
|
||||||
account.subscription(api_subscription_url(account.id)).unsubscribe if account.subscribed?
|
account.subscription(api_subscription_url(account.id)).unsubscribe if account.subscribed?
|
||||||
SuspendAccountService.new.call(account)
|
SuspendAccountService.new.call(account)
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,8 @@ class FanOutOnWriteService < BaseService
|
||||||
# Push a status into home and mentions feeds
|
# Push a status into home and mentions feeds
|
||||||
# @param [Status] status
|
# @param [Status] status
|
||||||
def call(status)
|
def call(status)
|
||||||
|
raise Mastodon::RaceConditionError if status.visibility.nil?
|
||||||
|
|
||||||
deliver_to_self(status) if status.account.local?
|
deliver_to_self(status) if status.account.local?
|
||||||
|
|
||||||
if status.direct_visibility?
|
if status.direct_visibility?
|
||||||
|
|
|
@ -14,3 +14,4 @@
|
||||||
%td= block.severity
|
%td= block.severity
|
||||||
|
|
||||||
= will_paginate @blocks, pagination_options
|
= will_paginate @blocks, pagination_options
|
||||||
|
= link_to 'Add new', new_admin_domain_block_path, class: 'button'
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
- content_for :page_title do
|
||||||
|
New domain block
|
||||||
|
|
||||||
|
= simple_form_for @domain_block, url: admin_domain_blocks_path do |f|
|
||||||
|
= render 'shared/error_messages', object: @domain_block
|
||||||
|
|
||||||
|
%p.hint The domain block will not prevent creation of account entries in the database, but will retroactively and automatically apply specific moderation methods on those accounts.
|
||||||
|
|
||||||
|
= f.input :domain, placeholder: 'Domain'
|
||||||
|
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false
|
||||||
|
|
||||||
|
%p.hint
|
||||||
|
%strong Silence
|
||||||
|
will make the account's posts invisible to anyone who isn't following them.
|
||||||
|
%strong Suspend
|
||||||
|
will remove all of the account's content, media, and profile data.
|
||||||
|
.actions
|
||||||
|
= f.button :button, 'Create block', type: :submit
|
|
@ -8,20 +8,25 @@
|
||||||
%li= filter_link_to 'Unresolved', action_taken: nil
|
%li= filter_link_to 'Unresolved', action_taken: nil
|
||||||
%li= filter_link_to 'Resolved', action_taken: '1'
|
%li= filter_link_to 'Resolved', action_taken: '1'
|
||||||
|
|
||||||
%table.table
|
= form_tag do
|
||||||
%thead
|
|
||||||
%tr
|
%table.table
|
||||||
%th ID
|
%thead
|
||||||
%th Target
|
|
||||||
%th Reported by
|
|
||||||
%th Comment
|
|
||||||
%th
|
|
||||||
%tbody
|
|
||||||
- @reports.each do |report|
|
|
||||||
%tr
|
%tr
|
||||||
%td= "##{report.id}"
|
%th
|
||||||
%td= link_to report.target_account.acct, admin_account_path(report.target_account.id)
|
%th ID
|
||||||
%td= link_to report.account.acct, admin_account_path(report.account.id)
|
%th Target
|
||||||
%td= truncate(report.comment, length: 30, separator: ' ')
|
%th Reported by
|
||||||
%td= table_link_to 'circle', 'View', admin_report_path(report)
|
%th Comment
|
||||||
|
%th
|
||||||
|
%tbody
|
||||||
|
- @reports.each do |report|
|
||||||
|
%tr
|
||||||
|
%td= check_box_tag 'select', report.id
|
||||||
|
%td= "##{report.id}"
|
||||||
|
%td= link_to report.target_account.acct, admin_account_path(report.target_account.id)
|
||||||
|
%td= link_to report.account.acct, admin_account_path(report.account.id)
|
||||||
|
%td= truncate(report.comment, length: 30, separator: ' ')
|
||||||
|
%td= table_link_to 'circle', 'View', admin_report_path(report)
|
||||||
|
|
||||||
= will_paginate @reports, pagination_options
|
= will_paginate @reports, pagination_options
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
= link_to remove_admin_report_path(@report, status_id: status.id), method: :post, class: 'icon-button', style: 'font-size: 24px; width: 24px; height: 24px', title: 'Delete' do
|
= link_to remove_admin_report_path(@report, status_id: status.id), method: :post, class: 'icon-button', style: 'font-size: 24px; width: 24px; height: 24px', title: 'Delete' do
|
||||||
= fa_icon 'trash'
|
= fa_icon 'trash'
|
||||||
|
|
||||||
- unless @report.action_taken?
|
- if !@report.action_taken?
|
||||||
%hr/
|
%hr/
|
||||||
|
|
||||||
%div{ style: 'overflow: hidden' }
|
%div{ style: 'overflow: hidden' }
|
||||||
|
@ -36,3 +36,9 @@
|
||||||
= link_to 'Suspend account', suspend_admin_report_path(@report), method: :post, class: 'button'
|
= link_to 'Suspend account', suspend_admin_report_path(@report), method: :post, class: 'button'
|
||||||
%div{ style: 'float: left' }
|
%div{ style: 'float: left' }
|
||||||
= link_to 'Mark as resolved', resolve_admin_report_path(@report), method: :post, class: 'button'
|
= link_to 'Mark as resolved', resolve_admin_report_path(@report), method: :post, class: 'button'
|
||||||
|
- elsif !@report.action_taken_by_account.nil?
|
||||||
|
%hr/
|
||||||
|
|
||||||
|
%p
|
||||||
|
%strong Action taken by:
|
||||||
|
= @report.action_taken_by_account.acct
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class AfterRemoteFollowRequestWorker
|
class AfterRemoteFollowRequestWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options retry: 5
|
sidekiq_options queue: 'pull', retry: 5
|
||||||
|
|
||||||
def perform(follow_request_id)
|
def perform(follow_request_id)
|
||||||
follow_request = FollowRequest.find(follow_request_id)
|
follow_request = FollowRequest.find(follow_request_id)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class AfterRemoteFollowWorker
|
class AfterRemoteFollowWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options retry: 5
|
sidekiq_options queue: 'pull', retry: 5
|
||||||
|
|
||||||
def perform(follow_id)
|
def perform(follow_id)
|
||||||
follow = Follow.find(follow_id)
|
follow = Follow.find(follow_id)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DomainBlockWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
def perform(domain_block_id)
|
||||||
|
BlockDomainService.new.call(DomainBlock.find(domain_block_id))
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,7 +5,7 @@ require 'csv'
|
||||||
class ImportWorker
|
class ImportWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options retry: false
|
sidekiq_options queue: 'pull', retry: false
|
||||||
|
|
||||||
def perform(import_id)
|
def perform(import_id)
|
||||||
import = Import.find(import_id)
|
import = Import.find(import_id)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class LinkCrawlWorker
|
class LinkCrawlWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options retry: false
|
sidekiq_options queue: 'pull', retry: false
|
||||||
|
|
||||||
def perform(status_id)
|
def perform(status_id)
|
||||||
FetchLinkCardService.new.call(Status.find(status_id))
|
FetchLinkCardService.new.call(Status.find(status_id))
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
class MergeWorker
|
class MergeWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
sidekiq_options queue: 'pull'
|
||||||
|
|
||||||
def perform(from_account_id, into_account_id)
|
def perform(from_account_id, into_account_id)
|
||||||
FeedManager.instance.merge_into_timeline(Account.find(from_account_id), Account.find(into_account_id))
|
FeedManager.instance.merge_into_timeline(Account.find(from_account_id), Account.find(into_account_id))
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class NotificationWorker
|
class NotificationWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options retry: 5
|
sidekiq_options queue: 'push', retry: 5
|
||||||
|
|
||||||
def perform(xml, source_account_id, target_account_id)
|
def perform(xml, source_account_id, target_account_id)
|
||||||
SendInteractionService.new.call(xml, Account.find(source_account_id), Account.find(target_account_id))
|
SendInteractionService.new.call(xml, Account.find(source_account_id), Account.find(target_account_id))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class ProcessingWorker
|
class ProcessingWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options backtrace: true
|
sidekiq_options queue: 'pull', backtrace: true
|
||||||
|
|
||||||
def perform(account_id, body)
|
def perform(account_id, body)
|
||||||
ProcessFeedService.new.call(body, Account.find(account_id))
|
ProcessFeedService.new.call(body, Account.find(account_id))
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
class RegenerationWorker
|
class RegenerationWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
def perform(account_id, timeline_type)
|
sidekiq_options queue: 'pull', backtrace: true
|
||||||
PrecomputeFeedService.new.call(timeline_type, Account.find(account_id))
|
|
||||||
|
def perform(account_id, _ = :home)
|
||||||
|
PrecomputeFeedService.new.call(:home, Account.find(account_id))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class SalmonWorker
|
class SalmonWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options backtrace: true
|
sidekiq_options queue: 'pull', backtrace: true
|
||||||
|
|
||||||
def perform(account_id, body)
|
def perform(account_id, body)
|
||||||
ProcessInteractionService.new.call(body, Account.find(account_id))
|
ProcessInteractionService.new.call(body, Account.find(account_id))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class ThreadResolveWorker
|
class ThreadResolveWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options retry: false
|
sidekiq_options queue: 'pull', retry: false
|
||||||
|
|
||||||
def perform(child_status_id, parent_url)
|
def perform(child_status_id, parent_url)
|
||||||
child_status = Status.find(child_status_id)
|
child_status = Status.find(child_status_id)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
class UnmergeWorker
|
class UnmergeWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
sidekiq_options queue: 'pull'
|
||||||
|
|
||||||
def perform(from_account_id, into_account_id)
|
def perform(from_account_id, into_account_id)
|
||||||
FeedManager.instance.unmerge_from_timeline(Account.find(from_account_id), Account.find(into_account_id))
|
FeedManager.instance.unmerge_from_timeline(Account.find(from_account_id), Account.find(into_account_id))
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
'no':
|
||||||
|
devise:
|
||||||
|
confirmations:
|
||||||
|
confirmed: Epostaddressen din er blitt bekreftet.
|
||||||
|
send_instructions: Du vil motta en epost med instruksjoner for hvordan bekrefte din epostaddresse om noen få minutter.
|
||||||
|
send_paranoid_instructions: Hvis din epostaddresse finnes i vår database vil du motta en epost med instruksjoner for hvordan bekrefte din epost om noen få minutter.
|
||||||
|
failure:
|
||||||
|
already_authenticated: Du er allerede innlogget.
|
||||||
|
inactive: Din konto er ikke blitt aktivert ennå.
|
||||||
|
invalid: Ugyldig %{authentication_keys} eller passord.
|
||||||
|
last_attempt: Du har ett forsøk igjen før kontoen din bli låst.
|
||||||
|
locked: Din konto er låst.
|
||||||
|
not_found_in_database: Ugyldig %{authentication_keys} eller passord.
|
||||||
|
timeout: Sesjonen din løp ut på tid. Logg inn på nytt for å fortsette.
|
||||||
|
unauthenticated: Du må logge inn eller registrere deg før du kan fortsette.
|
||||||
|
unconfirmed: Du må bekrefte epostadressen din før du kan fortsette.
|
||||||
|
mailer:
|
||||||
|
confirmation_instructions:
|
||||||
|
subject: 'Mastodon: Instruksjoner for å bekrefte epostadresse'
|
||||||
|
password_change:
|
||||||
|
subject: 'Mastodon: Passord endret'
|
||||||
|
reset_password_instructions:
|
||||||
|
subject: 'Mastodon: Hvordan nullstille passord?'
|
||||||
|
unlock_instructions:
|
||||||
|
subject: 'Mastodon: Instruksjoner for å gjenåpne konto'
|
||||||
|
omniauth_callbacks:
|
||||||
|
failure: Kunne ikke autentisere deg fra %{kind} fordi "%{reason}".
|
||||||
|
success: Vellykket autentisering fra %{kind}.
|
||||||
|
passwords:
|
||||||
|
no_token: Du har ingen tilgang til denne siden så lenge du ikke kommer fra en epost om nullstilling av passord. Hvis du kommer fra en passordnullstilling epost, dobbelsjekk at du brukte hele URLen.
|
||||||
|
send_instructions: Du vil motta en epost med instruksjoner for å nullstille passordet ditt om noen få minutter.
|
||||||
|
send_paranoid_instructions: Hvis epostadressen din finnes i databasen vår vil du motta en instruksjonsmail om passord nullstilling om noen få minutter.
|
||||||
|
updated: Passordet ditt har blitt endret. Du er nå logget inn.
|
||||||
|
updated_not_active: Passordet ditt har blitt endret.
|
||||||
|
registrations:
|
||||||
|
destroyed: Adjø! Kontoen din har blitt avsluttet. Vi håper at vi ser deg igjen snart.
|
||||||
|
signed_up: Velkommen! Registrasjonen var vellykket.
|
||||||
|
signed_up_but_inactive: Registrasjonen var vellykket. Vi kunne dessverre ikke logge deg inn fordi kontoen din ennå ikke har blitt aktivert.
|
||||||
|
signed_up_but_locked: Registrasjonen var vellykket. Vi kunne dessverre ikke logge deg inn fordi kontoen din har blitt låst.
|
||||||
|
signed_up_but_unconfirmed: En epostmelding med en bekreftelseslink har blitt sendt til din adresse. Klikk på linken i eposten for å aktivere kontoen din.
|
||||||
|
update_needs_confirmation: Du har oppdatert kontoen din, men vi må bekrefte din nye epostadresse. Sjekk eposten din og følg bekreftelseslinken for å bekrefte din nye epostadresse.
|
||||||
|
updated: Kontoen din ble oppdatert.
|
||||||
|
sessions:
|
||||||
|
already_signed_out: Logget ut.
|
||||||
|
signed_in: Logget inn.
|
||||||
|
signed_out: Logget ut.
|
||||||
|
unlocks:
|
||||||
|
send_instructions: Du vil motta en epost med instruksjoner for å åpne kontoen din om noen få minutter.
|
||||||
|
send_paranoid_instructions: Hvis kontoen din eksisterer vil du motta en epost med instruksjoner for å åpne kontoen din om noen få minutter.
|
||||||
|
unlocked: Kontoen din ble åpnet uten problemer. Logg på for å fortsette.
|
||||||
|
errors:
|
||||||
|
messages:
|
||||||
|
already_confirmed: har allerede blitt bekreftet, prøv å logg på istedet.
|
||||||
|
confirmation_period_expired: må bekreftes innen %{period}. Spør om en ny bekreftelsesmail istedet.
|
||||||
|
expired: har utløpt, spør om en ny en istedet
|
||||||
|
not_found: ikke funnet
|
||||||
|
not_locked: var ikke låst
|
||||||
|
not_saved:
|
||||||
|
one: '1 feil hindret denne %{resource} fra å bli lagret:'
|
||||||
|
other: "%{count} feil hindret denne %{resource} fra å bli lagret:"
|
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
'no':
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
doorkeeper/application:
|
||||||
|
name: Navn
|
||||||
|
redirect_uri: Omdirigerings-URI
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
doorkeeper/application:
|
||||||
|
attributes:
|
||||||
|
redirect_uri:
|
||||||
|
fragment_present: kan ikke inneholde ett fragment.
|
||||||
|
invalid_uri: må være en gyldig URI.
|
||||||
|
relative_uri: må være en absolutt URI.
|
||||||
|
secured_uri: må være en HTTPS/SSL URI.
|
||||||
|
doorkeeper:
|
||||||
|
applications:
|
||||||
|
buttons:
|
||||||
|
authorize: Autoriser
|
||||||
|
cancel: Avbryt
|
||||||
|
destroy: Ødelegg
|
||||||
|
edit: Endre
|
||||||
|
submit: Send inn
|
||||||
|
confirmations:
|
||||||
|
destroy: Er du sikker?
|
||||||
|
edit:
|
||||||
|
title: Endre applikasjon
|
||||||
|
form:
|
||||||
|
error: Whoops! Sjekk skjemaet ditt for mulige feil
|
||||||
|
help:
|
||||||
|
native_redirect_uri: Bruk %{native_redirect_uri} for lokale tester
|
||||||
|
redirect_uri: Bruk en linje per URI
|
||||||
|
scopes: Adskill omfang med mellomrom. La det være blankt for å bruke standard omfang.
|
||||||
|
index:
|
||||||
|
callback_url: Callback URL
|
||||||
|
name: Navn
|
||||||
|
new: Ny Applikasjon
|
||||||
|
title: Dine applikasjoner
|
||||||
|
new:
|
||||||
|
title: Ny Applikasjoner
|
||||||
|
show:
|
||||||
|
actions: Operasjoner
|
||||||
|
application_id: Applikasjon Id
|
||||||
|
callback_urls: Callback urls
|
||||||
|
scopes: Omfang
|
||||||
|
secret: Hemmelighet
|
||||||
|
title: 'Applikasjon: %{name}'
|
||||||
|
authorizations:
|
||||||
|
buttons:
|
||||||
|
authorize: Autoriser
|
||||||
|
deny: Avvis
|
||||||
|
error:
|
||||||
|
title: En feil oppsto
|
||||||
|
new:
|
||||||
|
able_to: Den vil ha mulighet til
|
||||||
|
prompt: Applikasjon %{client_name} spør om tilgang til din konto
|
||||||
|
title: Autorisasjon påkrevd
|
||||||
|
show:
|
||||||
|
title: Autoriserings kode
|
||||||
|
authorized_applications:
|
||||||
|
buttons:
|
||||||
|
revoke: Opphev
|
||||||
|
confirmations:
|
||||||
|
revoke: Opphev?
|
||||||
|
index:
|
||||||
|
application: Applikasjon
|
||||||
|
created_at: Autorisert
|
||||||
|
date_format: "%Y-%m-%d %H:%M:%S"
|
||||||
|
scopes: Omfang
|
||||||
|
title: Dine autoriserte applikasjoner
|
||||||
|
errors:
|
||||||
|
messages:
|
||||||
|
access_denied: Ressurseieren eller autoriserings tjeneren avviste forespørslen.
|
||||||
|
credential_flow_not_configured: Ressurseiers passord flyt feilet på grunn av at Doorkeeper.configure.resource_owner_from_credentials ikke var konfigurert.
|
||||||
|
invalid_client: Klient autentisering feilet på grunn av ukjent klient, ingen autentisering inkludert eller autentiserings metode som ikke er støttet.
|
||||||
|
invalid_grant: Autoriseringen er ugyldig, utløpt, opphevet, stemmer ikke overens med omdirigerings-URIen eller var utstedt til en annen klient.
|
||||||
|
invalid_redirect_uri: redirect urien som var inkludert er ikke gyldig.
|
||||||
|
invalid_request: Forespørslen mangler ett eller flere parametere, inkluderte ett parameter som ikke støttes eller har feil struktur.
|
||||||
|
invalid_resource_owner: Ressurseierens detaljer er ikke gyldig, eller så kan ikke eieren finnes.
|
||||||
|
invalid_scope: Det etterspurte omfanget er ugyldig, ukjent eller har feil struktur.
|
||||||
|
invalid_token:
|
||||||
|
expired: Tilgangsbeviset har utløpt
|
||||||
|
revoked: Tilgangsbeviset har blitt opphevet
|
||||||
|
unknown: Tilgangsbeviset er ugyldig
|
||||||
|
resource_owner_authenticator_not_configured: Ressurseier kunne ikke finnes fordi Doorkeeper.configure.resource_owner_authenticator ikke er konfigurert.
|
||||||
|
server_error: Autoriserings tjeneren støtte på en uventet hendelse som hindret den i å svare på forespørslen.
|
||||||
|
temporarily_unavailable: Autoriserings tjeneren kan ikke håndtere forespørslen grunnet en midlertidig overbelastning eller tjenervedlikehold.
|
||||||
|
unauthorized_client: Klienten har ikke autorisasjon for å utføre denne forespørslen med denne metoden.
|
||||||
|
unsupported_grant_type: Autorisasjons tildelings typen er ikke støttet av denne autoriserings tjeneren.
|
||||||
|
unsupported_response_type: Autorisasjons serveren støtter ikke denne typen av forespørsler.
|
||||||
|
flash:
|
||||||
|
applications:
|
||||||
|
create:
|
||||||
|
notice: Applikasjon opprettet.
|
||||||
|
destroy:
|
||||||
|
notice: Applikasjon slettet.
|
||||||
|
update:
|
||||||
|
notice: Applikasjon oppdatert.
|
||||||
|
authorized_applications:
|
||||||
|
destroy:
|
||||||
|
notice: Applikasjon opphevet.
|
||||||
|
layouts:
|
||||||
|
admin:
|
||||||
|
nav:
|
||||||
|
applications: Applikasjoner
|
||||||
|
oauth2_provider: OAuth2 tilbyder
|
||||||
|
application:
|
||||||
|
title: OAuth autorisering påkrevet
|
||||||
|
scopes:
|
||||||
|
follow: følg, blokker, avblokker, avfølg kontoer
|
||||||
|
read: lese dine data
|
||||||
|
write: poste på dine vegne
|
|
@ -0,0 +1,164 @@
|
||||||
|
---
|
||||||
|
'no':
|
||||||
|
about:
|
||||||
|
about_mastodon: Mastodon er et <em>gratis, åpen kildekode</em> sosialt nettverk. Et <em>desentralisert</em> alternativ til kommersielle plattformer. Slik kan det unngå risikoene ved å ha et enkelt selskap med monopol på din kommunikasjon. Velg en tjener du stoler på — uansett hvilken du velger så kan du interagere med alle andre. Alle kan kjøre sin egen Mastodon og delta sømløst i det sosiale nettverket.
|
||||||
|
about_this: Om denne instansen
|
||||||
|
apps: Applikasjoner
|
||||||
|
business_email: 'Bedriftsepost:'
|
||||||
|
contact: Kontakt
|
||||||
|
description_headline: Hva er %{domain}?
|
||||||
|
domain_count_after: andre instanser
|
||||||
|
domain_count_before: Koblet til
|
||||||
|
features:
|
||||||
|
api: Åpent api for applikasjoner og tjenester
|
||||||
|
blocks: Rikholdige blokkerings verktøy
|
||||||
|
characters: 500 tegn per post
|
||||||
|
chronology: Tidslinjer er kronologiske
|
||||||
|
ethics: 'Etisk design: Ingen reklame, ingen sporing'
|
||||||
|
gifv: GIFV sett og korte videoer
|
||||||
|
privacy: Finmaskete personvernsinnstillinger
|
||||||
|
public: Offentlige tidslinjer
|
||||||
|
features_headline: Hva skiller Mastodon fra andre sosiale nettverk
|
||||||
|
get_started: Kom i gang
|
||||||
|
links: Lenker
|
||||||
|
other_instances: Andre instanser
|
||||||
|
source_code: Kildekode
|
||||||
|
status_count_after: statuser
|
||||||
|
status_count_before: Hvem skrev
|
||||||
|
terms: Betingelser
|
||||||
|
user_count_after: brukere
|
||||||
|
user_count_before: Hjem til
|
||||||
|
accounts:
|
||||||
|
follow: Følg
|
||||||
|
followers: Følgere
|
||||||
|
following: Følger
|
||||||
|
nothing_here: Det er ingenting her!
|
||||||
|
people_followed_by: Folk som %{name} følger
|
||||||
|
people_who_follow: Folk som følger %{name}
|
||||||
|
posts: Poster
|
||||||
|
remote_follow: Følg fra andre instanser
|
||||||
|
unfollow: Avfølg
|
||||||
|
application_mailer:
|
||||||
|
settings: 'Endre foretrukne epost innstillinger: %{link}'
|
||||||
|
signature: Mastodon notiser fra %{instance}
|
||||||
|
view: 'Se:'
|
||||||
|
applications:
|
||||||
|
invalid_url: Den oppgitte URLen er ugyldig
|
||||||
|
auth:
|
||||||
|
change_password: Brukerdetaljer
|
||||||
|
didnt_get_confirmation: Fikk du ikke bekreftelsesmailen din?
|
||||||
|
forgot_password: Har du glemt passordet ditt?
|
||||||
|
login: Innlogging
|
||||||
|
logout: Logg ut
|
||||||
|
register: Bli med
|
||||||
|
resend_confirmation: Send bekreftelsesinstruksjoner på nytt
|
||||||
|
reset_password: Nullstill passord
|
||||||
|
set_new_password: Sett nytt passord
|
||||||
|
authorize_follow:
|
||||||
|
error: Uheldigvis så skjedde det en feil når vi prøvde å få tak i en konto fra en annen instans.
|
||||||
|
follow: Følg
|
||||||
|
prompt_html: 'Du (<strong>%{self}</strong>) har spurt om å følge:'
|
||||||
|
title: Følg %{acct}
|
||||||
|
datetime:
|
||||||
|
distance_in_words:
|
||||||
|
about_x_hours: "%{count}t"
|
||||||
|
about_x_months: "%{count}m"
|
||||||
|
about_x_years: "%{count}å"
|
||||||
|
almost_x_years: "%{count}å"
|
||||||
|
half_a_minute: Nylig
|
||||||
|
less_than_x_minutes: "%{count}min"
|
||||||
|
less_than_x_seconds: Nylig
|
||||||
|
over_x_years: "%{count}å"
|
||||||
|
x_days: "%{count}d"
|
||||||
|
x_minutes: "%{count}min"
|
||||||
|
x_months: "%{count}mo"
|
||||||
|
x_seconds: "%{count}s"
|
||||||
|
exports:
|
||||||
|
blocks: Du blokkerer
|
||||||
|
csv: CSV
|
||||||
|
follows: Du følger
|
||||||
|
storage: Media lagring
|
||||||
|
generic:
|
||||||
|
changes_saved_msg: Vellykket lagring av endringer!
|
||||||
|
powered_by: drevet av %{link}
|
||||||
|
save_changes: Lagre endringer
|
||||||
|
validation_errors:
|
||||||
|
one: Noe er ikke helt riktig ennå. Vær snill å se etter en gang til
|
||||||
|
other: Noe er ikke helt riktig ennå. Det er ennå %{count} feil å rette på
|
||||||
|
imports:
|
||||||
|
preface: Du kan importere data om mennesker du følger eller blokkerer inn til kontoen din på denne instansen, fra filer opprettet av eksporter fra andre instanser.
|
||||||
|
success: Din data ble mottatt og vil bli prosessert så fort som mulig.
|
||||||
|
types:
|
||||||
|
blocking: Blokkeringsliste
|
||||||
|
following: Følgeliste
|
||||||
|
upload: Opplastning
|
||||||
|
landing_strip_html: <strong>%{name}</strong> er en bruker på <strong>%{domain}</strong>. Du kan følge dem eller interagere med dem hvis du har en konto hvor som helst i fediverset. Hvis du ikke har en konto så kan du <a href="%{sign_up_path}">registrere deg her</a>.
|
||||||
|
notification_mailer:
|
||||||
|
digest:
|
||||||
|
body: 'Her er en kort oppsummering av hva du har gått glipp av på %{instance} siden du logget deg inn sist den %{since}:'
|
||||||
|
mention: "%{name} nevnte deg i:"
|
||||||
|
new_followers_summary:
|
||||||
|
one: Du har fått en ny følger. Jippi!
|
||||||
|
other: Du har fått %{count} nye følgere! Imponerende!
|
||||||
|
subject:
|
||||||
|
one: "1 ny hendelse siden ditt siste besøk \U0001F418"
|
||||||
|
other: "%{count} nye hendelser siden ditt siste besøk \U0001F418"
|
||||||
|
favourite:
|
||||||
|
body: 'Din status ble satt som favoritt av %{name}'
|
||||||
|
subject: "%{name} satte din status som favoritt."
|
||||||
|
follow:
|
||||||
|
body: "%{name} følger deg!"
|
||||||
|
subject: "%{name} følger deg"
|
||||||
|
follow_request:
|
||||||
|
body: "%{name} har spurt om å få lov til å følge deg"
|
||||||
|
subject: 'Ventende følger: %{name}'
|
||||||
|
mention:
|
||||||
|
body: 'Du ble nevnt av %{name} i:'
|
||||||
|
subject: Du ble nevnt av %{name}
|
||||||
|
reblog:
|
||||||
|
body: 'Din status fikk en boost av %{name}:'
|
||||||
|
subject: "%{name} ga din status en boost"
|
||||||
|
pagination:
|
||||||
|
next: Neste
|
||||||
|
prev: Forrige
|
||||||
|
remote_follow:
|
||||||
|
acct: Tast inn brukernavn@domene som du vil følge fra
|
||||||
|
missing_resource: Kunne ikke finne URLen for din konto
|
||||||
|
proceed: Fortsett med følging
|
||||||
|
prompt: 'Du kommer til å følge:'
|
||||||
|
settings:
|
||||||
|
authorized_apps: Autoriserte applikasjoner
|
||||||
|
back: Tilbake til Mastodon
|
||||||
|
edit_profile: Endre profil
|
||||||
|
export: Data eksport
|
||||||
|
import: Importer
|
||||||
|
preferences: Foretrukne valg
|
||||||
|
settings: Innstillinger
|
||||||
|
two_factor_auth: To-faktor autentisering
|
||||||
|
statuses:
|
||||||
|
open_in_web: Åpne i nettleser
|
||||||
|
over_character_limit: tegngrense på %{max} overskredet
|
||||||
|
show_more: Vis mer
|
||||||
|
visibilities:
|
||||||
|
private: Vis kun til følgere
|
||||||
|
public: Offentlig
|
||||||
|
unlisted: Offentlig, men vis ikke på offentlig tidslinje
|
||||||
|
stream_entries:
|
||||||
|
click_to_show: Klikk for å vise
|
||||||
|
reblogged: boostet
|
||||||
|
sensitive_content: Sensitivt innhold
|
||||||
|
time:
|
||||||
|
formats:
|
||||||
|
default: "%d, %b %Y, %H:%M"
|
||||||
|
two_factor_auth:
|
||||||
|
description_html: Hvis du skru på <strong>tofaktor autentisering</strong> vil innlogging kreve at du har telefonen din, som vil generere koder som du må taste inn.
|
||||||
|
disable: Skru av
|
||||||
|
enable: Skru på
|
||||||
|
instructions_html: "<strong>Scan denne QR-koden i Google Authenticator eller en lignende app på telefonen din</strong>. Fra nå av så vil denne applikasjonen generere koder for deg som skal brukes under innlogging"
|
||||||
|
plaintext_secret_html: 'Plain-text secret: <samp>%{secret}</samp>'
|
||||||
|
warning: Hvis du ikke kan konfigurere en autentikatorapp nå, så bør du trykke "Skru av"; ellers vil du ikke kunne logge inn.
|
||||||
|
users:
|
||||||
|
invalid_email: E-post addressen er ugyldig
|
||||||
|
invalid_otp_token: Ugyldig two-faktor kode
|
||||||
|
will_paginate:
|
||||||
|
page_gap: "…"
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
'no':
|
||||||
|
simple_form:
|
||||||
|
hints:
|
||||||
|
defaults:
|
||||||
|
avatar: PNG, GIF eller JPG. Maksimalt 2MB. Vil bli nedskalert til 120x120px
|
||||||
|
display_name: Maksimalt 30 tegn
|
||||||
|
header: PNG, GIF eller JPG. Maksimalt 2MB. Vil bli nedskalert til 700x335px
|
||||||
|
locked: Krever at du manuelt godkjenner følgere og setter standard beskyttelse av poster til kun-følgere
|
||||||
|
note: Maksimalt 160 tegn
|
||||||
|
imports:
|
||||||
|
data: CSV fil eksportert fra en annen Mastodon instans
|
||||||
|
labels:
|
||||||
|
defaults:
|
||||||
|
avatar: Avatar
|
||||||
|
confirm_new_password: Bekreft nytt passord
|
||||||
|
confirm_password: Bekreft passord
|
||||||
|
current_password: Nåværende passord
|
||||||
|
data: Data
|
||||||
|
display_name: Visningsnavn
|
||||||
|
email: E-post adresse
|
||||||
|
header: Header
|
||||||
|
locale: Språk
|
||||||
|
locked: Endre konto til privat
|
||||||
|
new_password: Nytt passord
|
||||||
|
note: Biografi
|
||||||
|
otp_attempt: To-faktor kode
|
||||||
|
password: Passord
|
||||||
|
setting_default_privacy: Leserettigheter for poster
|
||||||
|
type: Importeringstype
|
||||||
|
username: Brukernavn
|
||||||
|
interactions:
|
||||||
|
must_be_follower: Blokker meldinger fra ikke-følgere
|
||||||
|
must_be_following: Blokker meldinger fra folk du ikke følger
|
||||||
|
notification_emails:
|
||||||
|
digest: Send oppsummerings eposter
|
||||||
|
favourite: Send e-post når noen setter din status som favoritt
|
||||||
|
follow: Send e-post når noen følger deg
|
||||||
|
follow_request: Send e-post når noen spør om å få følge deg
|
||||||
|
mention: Send e-post når noen nevner deg
|
||||||
|
reblog: Send e-post når noen reblogger din status
|
||||||
|
'no': 'Nei'
|
||||||
|
required:
|
||||||
|
mark: "*"
|
||||||
|
text: påkrevd
|
||||||
|
'yes': 'Ja'
|
|
@ -14,11 +14,11 @@ SimpleNavigation::Configuration.run do |navigation|
|
||||||
settings.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url
|
settings.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url
|
||||||
end
|
end
|
||||||
|
|
||||||
primary.item :admin, safe_join([fa_icon('cogs fw'), 'Administration']), admin_accounts_url, if: proc { current_user.admin? } do |admin|
|
primary.item :admin, safe_join([fa_icon('cogs fw'), 'Administration']), admin_reports_url, if: proc { current_user.admin? } do |admin|
|
||||||
admin.item :reports, safe_join([fa_icon('flag fw'), 'Reports']), admin_reports_url, highlights_on: %r{/admin/reports}
|
admin.item :reports, safe_join([fa_icon('flag fw'), 'Reports']), admin_reports_url, highlights_on: %r{/admin/reports}
|
||||||
admin.item :accounts, safe_join([fa_icon('users fw'), 'Accounts']), admin_accounts_url, highlights_on: %r{/admin/accounts}
|
admin.item :accounts, safe_join([fa_icon('users fw'), 'Accounts']), admin_accounts_url, highlights_on: %r{/admin/accounts}
|
||||||
admin.item :pubsubhubbubs, safe_join([fa_icon('paper-plane-o fw'), 'PubSubHubbub']), admin_pubsubhubbub_index_url
|
admin.item :pubsubhubbubs, safe_join([fa_icon('paper-plane-o fw'), 'PubSubHubbub']), admin_pubsubhubbub_index_url
|
||||||
admin.item :domain_blocks, safe_join([fa_icon('lock fw'), 'Domain Blocks']), admin_domain_blocks_url
|
admin.item :domain_blocks, safe_join([fa_icon('lock fw'), 'Domain Blocks']), admin_domain_blocks_url, highlights_on: %r{/admin/domain_blocks}
|
||||||
admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url
|
admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url
|
||||||
admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url
|
admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url
|
||||||
admin.item :settings, safe_join([fa_icon('cogs fw'), 'Site Settings']), admin_settings_url
|
admin.item :settings, safe_join([fa_icon('cogs fw'), 'Site Settings']), admin_settings_url
|
||||||
|
|
|
@ -77,7 +77,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
namespace :admin do
|
namespace :admin do
|
||||||
resources :pubsubhubbub, only: [:index]
|
resources :pubsubhubbub, only: [:index]
|
||||||
resources :domain_blocks, only: [:index, :create]
|
resources :domain_blocks, only: [:index, :new, :create]
|
||||||
resources :settings, only: [:index, :update]
|
resources :settings, only: [:index, :update]
|
||||||
|
|
||||||
resources :reports, only: [:index, :show] do
|
resources :reports, only: [:index, :show] do
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddActionTakenByAccountIdToReports < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
add_column :reports, :action_taken_by_account_id, :integer
|
||||||
|
end
|
||||||
|
end
|
17
db/schema.rb
17
db/schema.rb
|
@ -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: 20170330164118) do
|
ActiveRecord::Schema.define(version: 20170403172249) 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"
|
||||||
|
@ -201,13 +201,14 @@ ActiveRecord::Schema.define(version: 20170330164118) do
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "reports", force: :cascade do |t|
|
create_table "reports", force: :cascade do |t|
|
||||||
t.integer "account_id", null: false
|
t.integer "account_id", null: false
|
||||||
t.integer "target_account_id", null: false
|
t.integer "target_account_id", null: false
|
||||||
t.bigint "status_ids", default: [], null: false, array: true
|
t.bigint "status_ids", default: [], null: false, array: true
|
||||||
t.text "comment", default: "", null: false
|
t.text "comment", default: "", null: false
|
||||||
t.boolean "action_taken", default: false, null: false
|
t.boolean "action_taken", default: false, null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.integer "action_taken_by_account_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "settings", force: :cascade do |t|
|
create_table "settings", force: :cascade do |t|
|
||||||
|
|
|
@ -33,7 +33,7 @@ services:
|
||||||
restart: always
|
restart: always
|
||||||
build: .
|
build: .
|
||||||
env_file: .env.production
|
env_file: .env.production
|
||||||
command: bundle exec sidekiq -q default -q mailers -q push
|
command: bundle exec sidekiq -q default -q mailers -q pull -q push
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- redis
|
- redis
|
||||||
|
|
|
@ -180,7 +180,7 @@ User=mastodon
|
||||||
WorkingDirectory=/home/mastodon/live
|
WorkingDirectory=/home/mastodon/live
|
||||||
Environment="RAILS_ENV=production"
|
Environment="RAILS_ENV=production"
|
||||||
Environment="DB_POOL=5"
|
Environment="DB_POOL=5"
|
||||||
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q push
|
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
|
||||||
TimeoutSec=15
|
TimeoutSec=15
|
||||||
Restart=always
|
Restart=always
|
||||||
|
|
||||||
|
|
|
@ -21,5 +21,6 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
||||||
| [social.mashek.net](https://social.mashek.net) |Themed and customised for Mashekstein Labs community. Selectively federates.|Yes|No|
|
| [social.mashek.net](https://social.mashek.net) |Themed and customised for Mashekstein Labs community. Selectively federates.|Yes|No|
|
||||||
| [masto.themimitoof.fr](https://masto.themimitoof.fr) |N/A|Yes|Yes|
|
| [masto.themimitoof.fr](https://masto.themimitoof.fr) |N/A|Yes|Yes|
|
||||||
| [social.imirhil.fr](https://social.imirhil.fr) |N/A|No|Yes|
|
| [social.imirhil.fr](https://social.imirhil.fr) |N/A|No|Yes|
|
||||||
|
| [social.wxcafe.net](https://social.wxcafe.net) |Open registrations, federates everywhere, no moderation yet|Yes|Yes|
|
||||||
|
|
||||||
Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
|
Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
|
||||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe BlockDomainService do
|
||||||
bad_status2
|
bad_status2
|
||||||
bad_attachment
|
bad_attachment
|
||||||
|
|
||||||
subject.call('evil.org', :suspend)
|
subject.call(DomainBlock.create!(domain: 'evil.org', severity: :suspend))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates a domain block' do
|
it 'creates a domain block' do
|
||||||
|
|
Loading…
Reference in New Issue