diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb index 64b5cb747..5682bdb01 100644 --- a/app/controllers/api/v1/accounts/credentials_controller.rb +++ b/app/controllers/api/v1/accounts/credentials_controller.rb @@ -21,7 +21,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController private def account_params - params.permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value]) + params.permit(:display_name, :note, :avatar, :header, :locked, :bot, :cat, :discoverable, fields_attributes: [:name, :value]) end def user_settings_params diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb index 0c15447a6..f78953828 100644 --- a/app/controllers/settings/profiles_controller.rb +++ b/app/controllers/settings/profiles_controller.rb @@ -20,7 +20,7 @@ class Settings::ProfilesController < Settings::BaseController private def account_params - params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value]) + params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :cat, :discoverable, fields_attributes: [:name, :value]) end def set_account diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 2d6b87659..655c290a7 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -24,6 +24,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' }, olm: { 'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId', 'claim' => { '@type' => '@id', '@id' => 'toot:claim' }, 'fingerprintKey' => { '@type' => '@id', '@id' => 'toot:fingerprintKey' }, 'identityKey' => { '@type' => '@id', '@id' => 'toot:identityKey' }, 'devices' => { '@type' => '@id', '@id' => 'toot:devices' }, 'messageFranking' => 'toot:messageFranking', 'messageType' => 'toot:messageType', 'cipherText' => 'toot:cipherText' }, suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' }, + is_cat: { 'isCat' => 'as:isCat' }, }.freeze def self.default_key_transform diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index 7f217ae9f..95854b4b0 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -28,6 +28,7 @@ class Formatter unless status.local? html = reformat(raw_content) html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify] + html = nyaize(html) if options[:nyaize] return html.html_safe # rubocop:disable Rails/OutputSafety end @@ -39,6 +40,7 @@ class Formatter html = encode_and_link_urls(html, linkable_accounts) html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify] html = simple_format(html, {}, sanitize: false) + html = nyaize(html) if options[:nyaize] html = html.delete("\n") html.html_safe # rubocop:disable Rails/OutputSafety @@ -192,6 +194,10 @@ class Formatter end # rubocop:enable Metrics/BlockNesting + def nyaize(html) + html.gsub(/な/, "にゃ").gsub(/ナ/, "ニャ").gsub(/ナ/, "ニャ").gsub(/[나-낳]/){|c|(c.ord + '냐'.ord - '나'.ord).chr} + end + def rewrite(text, entities) text = text.to_s diff --git a/app/models/account.rb b/app/models/account.rb index e6cf03fa8..5f769a68f 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -41,6 +41,7 @@ # featured_collection_url :string # fields :jsonb # actor_type :string +# cat :boolean default(FALSE), not null # discoverable :boolean # also_known_as :string is an Array # silenced_at :datetime diff --git a/app/models/status.rb b/app/models/status.rb index b426f9d5b..00a1c7827 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -129,7 +129,10 @@ class Status < ApplicationRecord ], thread: { account: :account_stat } - delegate :domain, to: :account, prefix: true + delegate :domain, + :cat, + to: :account, + prefix: true REAL_TIME_WINDOW = 6.hours diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index 759ef30f9..3b4c4df0d 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -12,7 +12,7 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer attributes :id, :type, :following, :followers, :inbox, :outbox, :featured, :featured_tags, :preferred_username, :name, :summary, - :url, :manually_approves_followers, + :url, :manually_approves_followers, :is_cat :discoverable has_one :public_key, serializer: ActivityPub::PublicKeySerializer @@ -138,6 +138,10 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer object.suspended? ? false : object.locked end + def is_cat + object.cat + end + def virtual_tags object.suspended? ? [] : (object.emojis + object.tags) end diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 189a62d0e..1b7946bcc 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -3,7 +3,7 @@ class REST::AccountSerializer < ActiveModel::Serializer include RoutingHelper - attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :group, :created_at, + attributes :id, :username, :acct, :display_name, :locked, :bot, :cat, :discoverable, :group, :created_at, :note, :url, :avatar, :avatar_static, :header, :header_static, :followers_count, :following_count, :statuses_count, :last_status_at diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index bb6df90b7..7df28832a 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -71,7 +71,7 @@ class REST::StatusSerializer < ActiveModel::Serializer end def content - Formatter.instance.format(object) + Formatter.instance.format(object, nyaize: object.account.cat) end def url diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 6afeb92d6..2621a07ae 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -112,6 +112,7 @@ class ActivityPub::ProcessAccountService < BaseService @account.followers_count = followers_total_items if followers_total_items.present? @account.hide_collections = following_private? || followers_private? @account.moved_to_account = @json['movedTo'].present? ? moved_account : nil + @account.cat = @json['isCat'] || false end def set_suspension! diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index fa15796d2..e03eb778a 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -4,12 +4,12 @@ .batch-table__row__content .status__content>< - if status.proper.spoiler_text.blank? - = Formatter.instance.format(status.proper, custom_emojify: true) + = Formatter.instance.format(status.proper, custom_emojify: true, nyaize: status.proper.account.cat) - else %details< %summary>< %strong> Content warning: #{Formatter.instance.format_spoiler(status.proper)} - = Formatter.instance.format(status.proper, custom_emojify: true) + = Formatter.instance.format(status.proper, custom_emojify: true, nyaize: status.proper.account.cat) - unless status.proper.media_attachments.empty? - if status.proper.media_attachments.first.video? diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index 9b7e1b65c..06b970367 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -31,7 +31,7 @@ = Formatter.instance.format_spoiler(status) %div.auto-dir - = Formatter.instance.format(status) + = Formatter.instance.format(status, nyaize: status.account.cat) - if status.media_attachments.size > 0 %p diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index 4885878f0..ce13ec2ac 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -29,6 +29,9 @@ .fields-group = f.input :bot, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.bot') + .fields-group + = f.input :cat, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.cat') + - if Setting.profile_directory .fields-group = f.input :discoverable, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.discoverable'), recommended: true diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml index 4c879472d..48b824b47 100644 --- a/app/views/statuses/_detailed_status.html.haml +++ b/app/views/statuses/_detailed_status.html.haml @@ -21,7 +21,7 @@ %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)}  %button.status__content__spoiler-link= t('statuses.show_more') .e-content - = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) + = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay, nyaize: status.account.cat) - if status.preloadable_poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do = render partial: 'statuses/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay } diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml index 236948a84..0465440f7 100644 --- a/app/views/statuses/_simple_status.html.haml +++ b/app/views/statuses/_simple_status.html.haml @@ -30,7 +30,7 @@ %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)}  %button.status__content__spoiler-link= t('statuses.show_more') .e-content - = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) + = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay, nyaize: status.account.cat) - if status.preloadable_poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do = render partial: 'statuses/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay } diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 20c916560..3f6acbb14 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -25,6 +25,7 @@ en: autofollow: People who sign up through the invite will automatically follow you avatar: PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px bot: This account mainly performs automated actions and might not be monitored + cat: This account is Cat context: One or multiple contexts where the filter should apply current_password: For security purposes please enter the password of the current account current_username: To confirm, please enter the username of the current account diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index abe986acd..0584b8122 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -25,6 +25,7 @@ ja: autofollow: 招待から登録した人が自動的にあなたをフォローするようになります avatar: "%{size}までのPNG、GIF、JPGが利用可能です。%{dimensions}pxまで縮小されます" bot: このアカウントは主に自動で動作し、人が見ていない可能性があります + cat: このアカウントはCatです context: フィルターを適用する対象 (複数選択可) current_password: 現在のアカウントのパスワードを入力してください current_username: 確認のため、現在のアカウントのユーザー名を入力してください diff --git a/db/migrate/20181122090024_add_cat_to_accounts.rb b/db/migrate/20181122090024_add_cat_to_accounts.rb new file mode 100644 index 000000000..cfd4ea6d7 --- /dev/null +++ b/db/migrate/20181122090024_add_cat_to_accounts.rb @@ -0,0 +1,7 @@ +class AddCatToAccounts < ActiveRecord::Migration[5.2] + disable_ddl_transaction! + + def change + add_column :accounts, :cat, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 18bf1d4ca..34cdabff9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -180,6 +180,7 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do t.string "featured_collection_url" t.jsonb "fields" t.string "actor_type" + t.boolean "cat", default: false, null: false t.boolean "discoverable" t.string "also_known_as", array: true t.datetime "silenced_at"