diff --git a/.env.test b/.env.test
index 761d0d9210690d..d06c73f2f3438b 100644
--- a/.env.test
+++ b/.env.test
@@ -3,3 +3,8 @@ NODE_ENV=tests
# Federation
LOCAL_DOMAIN=cb6e6126.ngrok.io
LOCAL_HTTPS=true
+# Elasticsearch
+ES_ENABLED=true
+ES_HOST=localhost
+ES_PORT=9200
+ES_PREFIX=test
diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml
index ecded2cc2fa67e..d21bf27777aecf 100644
--- a/.github/workflows/test-ruby.yml
+++ b/.github/workflows/test-ruby.yml
@@ -113,6 +113,7 @@ jobs:
CAS_ENABLED: true
BUNDLE_WITH: 'pam_authentication test'
CI_JOBS: ${{ matrix.ci_job }}/4
+ ES_ENABLED: false
strategy:
fail-fast: false
@@ -192,6 +193,7 @@ jobs:
DISABLE_SIMPLECOV: true
RAILS_ENV: test
BUNDLE_WITH: test
+ ES_ENABLED: false
strategy:
fail-fast: false
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c1a5fef7983835..a6ed08590a92fc 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,46 +1,36 @@
-# Contributing
+# CONTRIBUTING
-Thank you for considering contributing to Mastodon ð
+kmyblueã¯ãã³ãã¥ããã£ã®æèŠãèãã«ã¯èããŸããå°å
¥ããã»ããªãã¯ç®¡ç人ã決å®ããŸãã
-You can contribute in the following ways:
+## ãã°å ±å
-- Finding and reporting bugs
-- Translating the Mastodon interface into various languages
-- Contributing code to Mastodon by fixing bugs or implementing features
-- Improving the documentation
+ãã°ã«ã€ããŠãææ°ãããéå»ã®ããŒãžã§ã³ãžã®å¯Ÿå¿ã¯ç¹å¥ãªå Žå以å€ã¯è¡ããŸããã
-If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
+以äžã®ããããã®æ¹æ³ã§å ±åããŠãã ããã
-## Bug reports
+- [GitHub Issues](https://github.com/kmycode/mastodon/issues)
+- [kmyblueéçºè
ãžã®é£çµ¡](https://kmy.blue/@askyq)
+- [kmyblueéçºè
ãžã®ã¡ãŒã«](https://kmy.blue/about)
-Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected.
+## 翻蚳ããã«ãªã¯ãšã¹ã
-## Translations
+æ°ããæ©èœãæ¢åæ©èœã®ä¿®æ£ã«ã€ããŠã¯ããã«ãªã¯ãšã¹ãã®ããã«ã³ãŒããäœæããåã«ããŸãGitHub Issuesã§æ©èœã®ææ¡ãè¡ãkmyblueéçºè
ã®èããèãããšãããããããŸãããã°ä¿®æ£ã翻蚳ããã¹ãã³ãŒããªã©ã¯åºæ¬åãå
¥ããŸãããäŸåã¢ãžã¥ãŒã«ã®ããŒãžã§ã³ã¢ããã«ã€ããŠã¯æ¬å®¶Mastodonãããå
ã«è¡ããªãããã«ããŠãã ããã
-You can submit translations via [Crowdin](https://crowdin.com/project/mastodon). They are periodically merged into the codebase.
+ãã«ãªã¯ãšã¹ãã®ã¿ã€ãã«ã«ã¯ããã«ãªã¯ãšã¹ãã®å
容ãæ確ã«ãªããããªãã®ãèšå®ããŠãã ããã
-[![Crowdin](https://d322cqt584bo4o.cloudfront.net/mastodon/localized.svg)](https://crowdin.com/project/mastodon)
+### kmyblueã®éçºæ¹é
-## Pull requests
+äžèšã®ãã®ã«ççŸããªããã°ãããšã¯ç®¡ç人ã®æå次第ã§ãã
-**Please use clean, concise titles for your pull requests.** Unless the pull request is about refactoring code, updating dependencies or other internal tasks, assume that the person reading the pull request title is not a programmer or Mastodon developer, but instead a Mastodon user or server administrator, and **try to describe your change or fix from their perspective**. We use commit squashing, so the final commit in the main branch will carry the title of the pull request, and commits from the main branch are fed into the changelog. The changelog is separated into [keepachangelog.com categories](https://keepachangelog.com/en/1.0.0/), and while that spec does not prescribe how the entries ought to be named, for easier sorting, start your pull request titles using one of the verbs "Add", "Change", "Deprecate", "Remove", or "Fix" (present tense).
+- **èªåã®æçš¿ãèŠããããªã人ã«èŠããªã**
+- **ä»äººã®èŠãããªãæçš¿ãèŠãªã**
+- ãã ãæ¬å®¶Mastodonã§äžèšååã«ççŸããæ©èœãè¿œå ãããå Žåã¯åŸã
+- ç»é¢ãéšããããããããªæ©èœïŒçµµæåã倧ãã衚瀺ãããªã©ïŒã¯è¿œå ããªãããæ§ããã«ããããã ãä»ã®ãœãããŠã§ã¢ã«ãå°å
¥ããå©çšè
ãå€ãããå Žåãªã©ã¯å¥éå€æããŠããªããã¢ãŠãå¯èœãªèšå®é
ç®ãšãšãã«è¿œå ãã
+- è² è·ãèããäžãããããªæ©èœã¯ã§ããã ãè¿œå ããªã
-Example:
+kmyblueãæå³çã«å®è£
ããŠããªãæ©èœã¯ãäŸãã°ä»¥äžã®ãã®ããããŸãã詳ããçç±ãç¥ãããå Žåã¯[ãã®èšäºãåç
§ããã](https://note.com/kmycode/n/n463410b5e03c)ãå¥éãåãåãããã ããããã¡ããæ確ãªæ ¹æ ãããå Žåãããªãã¯ããã«æè°ããæš©å©ãæããŸãããããªãããã®kmyblueããã©ãŒã¯ããŠæ°ãããªããžããªãäœãã»ããããèªç±ã§ãããã
-| Not ideal | Better |
-| ------------------------------------ | ------------------------------------------------------------- |
-| Fixed NoMethodError in RemovalWorker | Fix nil error when removing statuses caused by race condition |
-
-It is not always possible to phrase every change in such a manner, but it is desired.
-
-**The smaller the set of changes in the pull request is, the quicker it can be reviewed and merged.** Splitting tasks into multiple smaller pull requests is often preferable.
-
-**Pull requests that do not pass automated checks may not be reviewed**. In particular, you need to keep in mind:
-
-- Unit and integration tests (rspec, jest)
-- Code style rules (rubocop, eslint)
-- Normalization of locale files (i18n-tasks)
-
-## Documentation
-
-The [Mastodon documentation](https://docs.joinmastodon.org) is a statically generated site. You can [submit merge requests to mastodon/documentation](https://github.com/mastodon/documentation).
+- åŒçšæ©èœ
+- ãæ°ã«å
¥ãäžèŠ§ã®å
Ž
+- ããã¯ããŒã¯åé¡ã®å
Ž
+- ä»ã®ãµãŒããŒã®æçš¿ã«å¯ŸããŠä»ã®ãµãŒããŒã®ã¢ã«ãŠã³ããè¡ã£ãçµµæåãªã¢ã¯ã·ã§ã³ã®åãå
¥ã
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 00000000000000..f3f43742d0c2aa
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,60 @@
+# kmyblueã€ã³ã¹ããŒã«æé
+
+## å
±éã®æ³šæäºé
+
+### å¿
é ãœãããŠã§ã¢ã®ããŒãžã§ã³
+
+RubyãElasticSearchãImageMagickãPostgreSQLãªã©å¿
é ãœãããŠã§ã¢ã®ããŒãžã§ã³ã¯ãæ¬å®¶Mastodonã«æºããŸãããªãªãŒã¹ããŒãã«å¯Ÿå¿ããæ¬å®¶MastodonããŒãžã§ã³ãèšèŒãããŠããŸãã®ã§ãæ¬å®¶Mastodonã®ãªãªãŒã¹ããŒããã察å¿ããããŒãžã§ã³ãæ¢ããŠèª¿ã¹ãŠãã ããã
+
+### äžè¬çãªæ³šæäºé
+
+kmyblueã¯é »ç¹ã«ããŒãžã§ã³ã¢ãããè¡ããŸãã
+
+- æ¬å®¶Mastodonã®éçºäžã®ããŒãžã§ã³ãå¹³ç¶ãšåã蟌ã¿ãŸã
+- ãã°ãå«ãŸããŠããããšããããŸã
+- ç¹ã«ææ°ã³ãããã§ã¯ããããã°çšã³ãŒããã`kmy.blue`æ¬çªãµãŒããŒã§åäœç¢ºèªãè¡ãããã®ã³ãŒããå«ãŸããŠããå ŽåããããŸãããã©ã³ãã®ææ°ã³ãããã§ã¯ãªãææ°ã¿ã°ãåã蟌ãããšã匷ãããããããŸã
+
+### ElasticSearchã䜿çšããå Žå
+
+kmyblueã§ã¯ãsudachiã®äœ¿çšãåæãšããŠããŸãã
+
+äžèšURLãããElasticSearchã«Sudachiãã©ã°ã€ã³ãè¿œå ããŠãã ããã
+ãã ãèŸæžãã¡ã€ã«ïŒsudachi dictionary archiveïŒã¯æé æžã§æ瀺ããããã¹ã§ã¯ãªã`/etc/elasticsearch/sudachi`ã«æ ŒçŽããŠãã ããã
+
+https://github.com/WorksApplications/elasticsearch-sudachi
+
+Sudachiã€ã³ã¹ããŒã«çµäºåŸãè¿œå ã§`/etc/elasticsearch/sudachi/config.json`ã«äžèšãèšè¿°ããŠä¿åããŠãã ããã`system_full.dic`ã䜿çšããå Žåã¯é©å®`systemDict`ããããã£ã®å
容ã眮ãæããŠãã ããã
+
+```json
+{
+ "systemDict": "system_core.dic"
+}
+```
+
+## æ°èŠã€ã³ã¹ããŒã«ã®å Žå
+
+1. æ¬å®¶Mastodonãšã»ããã¢ããæé ã¯ã»ãšãã©äžç·ã§ããkmyblueãç¬èªã«å¿
é ãœãããŠã§ã¢ãè¿œå ããããã§ã¯ãããŸããããã ãkmyblueã¯Mastodonã®éçºäžã³ãŒããåã蟌ãã§ããã®ã§ãRubyãªã©ã®ããŒãžã§ã³ã¢ããäœæ¥ãå¿
èŠã«ãªãå ŽåããããŸããMastodonå
¬åŒã®ã»ããã¢ããæé ãç²ä¿¡ãããç»é¢ã®æ瀺ã«åŸã£ãŠã€ã³ã¹ããŒã«ãé²ããŠãã ãããCloudFlareãçµã¿åãããŠã»ããã¢ãããããšãããµãŒããŒã«æ¥ç¶ãããš400ãåºããªã©ã®ãã©ãã«ãåºãããšããããŸããã倧æµã¯Mastodonæ¬å®¶ç±æ¥ã®ãã©ãã«ã ãšæãããã®ã§åºæ¬ãµããŒãã¯ããŸãã
+2. ãã ã²ãšã€å·®ç°ããããŸããGitãªããžããªã¯ãã®kmyblueã«åããŠãã ããã`kb_development`ãã©ã³ãã®ææ°ã³ãããã§ã¯ãªãã`kb`ã§å§ãŸãææ°ã®ã¿ã°ãåã蟌ãããšã匷ãããããããŸã
+
+## æ¬å®¶Mastodonããã®ãã€ã°ã¬ãŒã·ã§ã³ã®å Žå
+
+kmyblueããæ¬å®¶Mastodonã«æ»ãããå ŽåããããšæããŸãã®ã§ã**å¿
ãããŒã¿ããŒã¹ã®ããã¯ã¢ããããšã£ãŠãã ãã**ã
+
+1. kmyblueã®ãªãªãŒã¹ããŒãã«ãkmyblueããŒãžã§ã³ã«å¯Ÿå¿ããæ¬å®¶Mastodonã®ããŒãžã§ã³ãèšèŒãããŠããŸãããããåç
§ããŠããŸãæ¬å®¶Mastodonããã®ããŒãžã§ã³ãŸã§ããŒãžã§ã³ã¢ããããŠãã ãã
+2. Gitã®ãªã¢ãŒãã«kmyblueãè¿œå ããŠããã®ãŸãŸãã§ãã¯ã¢ãŠãããŠãã ãã
+3. ããŒã¿ããŒã¹ã®ãã€ã°ã¬ãŒã·ã§ã³ãªã©ãè¡ã£ãŠãã ãã
+
+```
+sudo systemctl stop mastodon-*
+
+bundle install
+yarn install
+RAILS_ENV=production bin/rails db:migrate
+RAILS_ENV=production bin/rails assets:clobber
+RAILS_ENV=production bin/rails assets:precompile
+
+# ElasticSearchã䜿çšããå Žå
+RAILS_ENV=production bin/tootctl search deploy
+
+sudo systemctl start mastodon-web mastodon-streaming@4000 mastodon-sidekiq
+```
diff --git a/README.md b/README.md
index 768a1e876421e1..13885c96f80fc6 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,19 @@ kmyblueã¯[Mastodon](https://github.com/mastodon/mastodon)ã®ãã©ãŒã¯ã§ã
kmyblueã¯ãã©ãŒã¯åã§ãããåæã«[ãµãŒããŒå](https://kmy.blue)ã§ããããŸãã以äžã¯ç¹ã«èšè¿°ããªãéãããã©ãŒã¯ãšããŠã®kmyblueããããŸãã
-kmyblue㯠AGPL ã©ã€ã»ã³ã¹ã§å
¬éãããŠãããããã©ãªãã§ãèªç±ã«ãã©ãŒã¯ãããã®ãœãŒã¹ã³ãŒããå
ã«èªåã§ãµãŒããŒãç«ãŠãŠå
¬éããããšãã§ããŸãããŸã ActivityPub ã«åå ããããšãã§ããŸãããµãŒããŒkmyblueã¯åµäœäœå®¶åãã®ãã®ã§ããããã©ãŒã¯ãšããŠã®kmyblueã¯äœè
ã®å«ããªæ¿æ²»ã«é¢ããéæ¿ãªè©±ãåãæ±ãã³ãã¥ããã£ãåµäœæŽ»åã®äžéšïŒãšãé¢ä¿å«ãïŒãŸãã¯å
šäœãåŠå®ããã³ãã¥ããã£ãªã©ãå¹³çã«ã䜿ãããã ããŸããããµãŒããŒkmyblueã®ã«ãŒã«ãé©çšããå¿
èŠããããŸããã
-ãã ãkmyblueã«ãããŠãã¹ãã³ãŒãã¯é£Ÿãã§ãããªããããäžå
·åãçºçããŠãèªå·±è²¬ä»»ã«ãªããŸããæ¢ç¥ã®ãã°ãããã€ããããŸãããçŽãäºå®ã®ãªããã®ãå«ãŸããŸãã
+kmyblue㯠AGPL ã©ã€ã»ã³ã¹ã§å
¬éãããŠãããããã©ãªãã§ãèªç±ã«ãã©ãŒã¯ãããã®ãœãŒã¹ã³ãŒããå
ã«èªåã§ãµãŒããŒãç«ãŠãŠå
¬éããããšãã§ããŸãããŸã ActivityPub ã«åå ããããšãã§ããŸãã確ãã«ãµãŒããŒkmyblueã¯åµäœäœå®¶åãã®ãã®ã§ããããã©ãŒã¯ãšããŠã®kmyblueã¯äœè
ãšæ¿æ²»çã«å¯Ÿç«ããã³ãã¥ããã£ãåµäœæŽ»åã®äžéšïŒãšãé¢ä¿å«ãïŒãŸãã¯å
šäœãåŠå®ããã³ãã¥ããã£ãªã©ã«ãå¹³çã«ã䜿ãããã ããŸãããããªãã³ãã¥ããã£ãkmyblueãã©ãŒã¯ã䜿çšããŠããããèªäœã«äœè
ãæè°ããããšããããŸããããµãŒããŒkmyblueã®ã«ãŒã«ãé©çšããå¿
èŠããªãããAnyone But Kmyblueããªã«ãŒã«ãèšå®ããããšãã蚱容ãããŸãã
+ãã ãkmyblueã«ãããŠ**ãã¹ãã³ãŒãã¯é£Ÿã**ã§ãããããŸãããç¬èªæ©èœã®ãã¹ããèšè¿°ããã ãã§ãªããæ¬å®¶ã®ãã¹ãã³ãŒãã®è£åŒ·ãè¡ã£ãŠãããŸããã確èªæŒãã¯å¿
ãçºçãããã®ã§ããäžå
·åãçºçããŠãèªå·±è²¬ä»»ã«ãªããŸããæ¢ç¥ã®ãã°ãããã€ããããŸãããçŽãäºå®ã®ãªããã®ãå«ãŸããŸãã
ãã¹ãã³ãŒããLint ã©ã¡ããåããŠããŸãã
+## ã€ã³ã¹ããŒã«æ¹æ³
+
+INSTALL.mdãåç
§ããŠãã ããã
+
+## éçºãžã®åå æ¹æ³
+
+CONTRIBUTING.mdãåç
§ããŠãã ããã
+
## kmyblueã®åŒ·ã¿
### æ¬å®¶Mastodonãžã®ç©æ¥µçè¿œåŸ
diff --git a/app/chewy/accounts_index.rb b/app/chewy/accounts_index.rb
index c854cdf01c3a5f..ad3816e4d63d75 100644
--- a/app/chewy/accounts_index.rb
+++ b/app/chewy/accounts_index.rb
@@ -1,7 +1,72 @@
# frozen_string_literal: true
class AccountsIndex < Chewy::Index
- settings index: index_preset(refresh_interval: '30s'), analysis: {
+ DEVELOPMENT_SETTINGS = {
+ filter: {
+ english_stop: {
+ type: 'stop',
+ stopwords: '_english_',
+ },
+
+ english_stemmer: {
+ type: 'stemmer',
+ language: 'english',
+ },
+
+ english_possessive_stemmer: {
+ type: 'stemmer',
+ language: 'possessive_english',
+ },
+ },
+
+ analyzer: {
+ natural: {
+ tokenizer: 'standard',
+ filter: %w(
+ lowercase
+ asciifolding
+ cjk_width
+ elision
+ english_possessive_stemmer
+ english_stop
+ english_stemmer
+ ),
+ },
+
+ sudachi_analyzer: {
+ tokenizer: 'standard',
+ filter: %w(
+ lowercase
+ asciifolding
+ cjk_width
+ elision
+ english_possessive_stemmer
+ english_stop
+ english_stemmer
+ ),
+ },
+
+ verbatim: {
+ tokenizer: 'standard',
+ filter: %w(lowercase asciifolding cjk_width),
+ },
+
+ edge_ngram: {
+ tokenizer: 'edge_ngram',
+ filter: %w(lowercase asciifolding cjk_width),
+ },
+ },
+
+ tokenizer: {
+ edge_ngram: {
+ type: 'edge_ngram',
+ min_gram: 1,
+ max_gram: 15,
+ },
+ },
+ }.freeze
+
+ PRODUCTION_SETTINGS = {
filter: {
english_stop: {
type: 'stop',
@@ -77,7 +142,9 @@ class AccountsIndex < Chewy::Index
discard_punctuation: 'true',
},
},
- }
+ }.freeze
+
+ settings index: index_preset(refresh_interval: '30s'), analysis: Rails.env.test? ? DEVELOPMENT_SETTINGS : PRODUCTION_SETTINGS
index_scope ::Account.searchable.includes(:account_stat)
diff --git a/app/chewy/public_statuses_index.rb b/app/chewy/public_statuses_index.rb
index 4bcbe817d9af1f..d152b520390077 100644
--- a/app/chewy/public_statuses_index.rb
+++ b/app/chewy/public_statuses_index.rb
@@ -38,6 +38,19 @@ class PublicStatusesIndex < Chewy::Index
),
},
+ sudachi_analyzer: {
+ tokenizer: 'standard',
+ filter: %w(
+ lowercase
+ asciifolding
+ cjk_width
+ elision
+ english_possessive_stemmer
+ english_stop
+ english_stemmer
+ ),
+ },
+
hashtag: {
tokenizer: 'keyword',
filter: %w(
@@ -126,7 +139,7 @@ class PublicStatusesIndex < Chewy::Index
},
}.freeze
- settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: PRODUCTION_SETTINGS
+ settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: Rails.env.test? ? DEVELOPMENT_SETTINGS : PRODUCTION_SETTINGS
index_scope ::Status.unscoped
.kept
diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb
index 5c993422de8421..3b83e2f31c1a51 100644
--- a/app/chewy/statuses_index.rb
+++ b/app/chewy/statuses_index.rb
@@ -37,6 +37,19 @@ class StatusesIndex < Chewy::Index
),
},
+ sudachi_analyzer: {
+ tokenizer: 'standard',
+ filter: %w(
+ lowercase
+ asciifolding
+ cjk_width
+ elision
+ english_possessive_stemmer
+ english_stop
+ english_stemmer
+ ),
+ },
+
hashtag: {
tokenizer: 'keyword',
filter: %w(
@@ -129,7 +142,7 @@ class StatusesIndex < Chewy::Index
},
}.freeze
- settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: PRODUCTION_SETTINGS
+ settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: Rails.env.test? ? DEVELOPMENT_SETTINGS : PRODUCTION_SETTINGS
index_scope ::Status.unscoped.kept.without_reblogs.includes(
:media_attachments,
diff --git a/app/controllers/api/v1/antennas_controller.rb b/app/controllers/api/v1/antennas_controller.rb
index c4b00c7784856d..37bfb7f55242f5 100644
--- a/app/controllers/api/v1/antennas_controller.rb
+++ b/app/controllers/api/v1/antennas_controller.rb
@@ -42,6 +42,6 @@ def set_antenna
end
def antenna_params
- params.permit(:title, :list_id, :insert_feeds, :stl, :with_media_only, :ignore_reblog)
+ params.permit(:title, :list_id, :insert_feeds, :stl, :ltl, :with_media_only, :ignore_reblog)
end
end
diff --git a/app/controllers/settings/preferences/other_controller.rb b/app/controllers/settings/preferences/other_controller.rb
index a19fbf5c48c3c7..77b4fe10f832a9 100644
--- a/app/controllers/settings/preferences/other_controller.rb
+++ b/app/controllers/settings/preferences/other_controller.rb
@@ -1,6 +1,13 @@
# frozen_string_literal: true
class Settings::Preferences::OtherController < Settings::Preferences::BaseController
+ include DtlHelper
+
+ def show
+ @dtl_enabled = DTL_ENABLED
+ @dtl_tag = DTL_TAG
+ end
+
private
def after_update_redirect_path
diff --git a/app/helpers/dtl_helper.rb b/app/helpers/dtl_helper.rb
new file mode 100644
index 00000000000000..d3c3a8c6621d00
--- /dev/null
+++ b/app/helpers/dtl_helper.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+module DtlHelper
+ DTL_ENABLED = ENV.fetch('DTL_ENABLED', 'false') == 'true'
+ DTL_TAG = ENV.fetch('DTL_TAG', 'kmyblue')
+end
diff --git a/app/javascript/icons/android-chrome-144x144.png b/app/javascript/icons/android-chrome-144x144.png
old mode 100644
new mode 100755
index 698fb4a260b136..d636e94c43bf42
Binary files a/app/javascript/icons/android-chrome-144x144.png and b/app/javascript/icons/android-chrome-144x144.png differ
diff --git a/app/javascript/icons/android-chrome-192x192.png b/app/javascript/icons/android-chrome-192x192.png
old mode 100644
new mode 100755
index 2b6b632648f6b1..4a2681ffb93418
Binary files a/app/javascript/icons/android-chrome-192x192.png and b/app/javascript/icons/android-chrome-192x192.png differ
diff --git a/app/javascript/icons/android-chrome-256x256.png b/app/javascript/icons/android-chrome-256x256.png
old mode 100644
new mode 100755
index 51e3849a263062..8fab493ede6d3d
Binary files a/app/javascript/icons/android-chrome-256x256.png and b/app/javascript/icons/android-chrome-256x256.png differ
diff --git a/app/javascript/icons/android-chrome-36x36.png b/app/javascript/icons/android-chrome-36x36.png
old mode 100644
new mode 100755
index 925f69c4fc7109..335d012db1c00c
Binary files a/app/javascript/icons/android-chrome-36x36.png and b/app/javascript/icons/android-chrome-36x36.png differ
diff --git a/app/javascript/icons/android-chrome-384x384.png b/app/javascript/icons/android-chrome-384x384.png
old mode 100644
new mode 100755
index 9d256a83cb3af2..02b1e6fcedd9fd
Binary files a/app/javascript/icons/android-chrome-384x384.png and b/app/javascript/icons/android-chrome-384x384.png differ
diff --git a/app/javascript/icons/android-chrome-48x48.png b/app/javascript/icons/android-chrome-48x48.png
old mode 100644
new mode 100755
index bcfe7475d0750b..43cf411b8c0680
Binary files a/app/javascript/icons/android-chrome-48x48.png and b/app/javascript/icons/android-chrome-48x48.png differ
diff --git a/app/javascript/icons/android-chrome-512x512.png b/app/javascript/icons/android-chrome-512x512.png
old mode 100644
new mode 100755
index bffacfb699c6b1..1856b80c7cb972
Binary files a/app/javascript/icons/android-chrome-512x512.png and b/app/javascript/icons/android-chrome-512x512.png differ
diff --git a/app/javascript/icons/android-chrome-72x72.png b/app/javascript/icons/android-chrome-72x72.png
old mode 100644
new mode 100755
index 16679d5731a6d6..335008bf852f7b
Binary files a/app/javascript/icons/android-chrome-72x72.png and b/app/javascript/icons/android-chrome-72x72.png differ
diff --git a/app/javascript/icons/android-chrome-96x96.png b/app/javascript/icons/android-chrome-96x96.png
old mode 100644
new mode 100755
index 9ade87cf32c06b..d1cb0958220556
Binary files a/app/javascript/icons/android-chrome-96x96.png and b/app/javascript/icons/android-chrome-96x96.png differ
diff --git a/app/javascript/icons/apple-touch-icon-1024x1024.png b/app/javascript/icons/apple-touch-icon-1024x1024.png
old mode 100644
new mode 100755
index 8ec371eb27ddbe..c2a2d516ef5b03
Binary files a/app/javascript/icons/apple-touch-icon-1024x1024.png and b/app/javascript/icons/apple-touch-icon-1024x1024.png differ
diff --git a/app/javascript/icons/apple-touch-icon-114x114.png b/app/javascript/icons/apple-touch-icon-114x114.png
old mode 100644
new mode 100755
index e1563f51e5758b..218b4154390789
Binary files a/app/javascript/icons/apple-touch-icon-114x114.png and b/app/javascript/icons/apple-touch-icon-114x114.png differ
diff --git a/app/javascript/icons/apple-touch-icon-120x120.png b/app/javascript/icons/apple-touch-icon-120x120.png
old mode 100644
new mode 100755
index e9a5f5b0e57595..be53bc7c1015b9
Binary files a/app/javascript/icons/apple-touch-icon-120x120.png and b/app/javascript/icons/apple-touch-icon-120x120.png differ
diff --git a/app/javascript/icons/apple-touch-icon-144x144.png b/app/javascript/icons/apple-touch-icon-144x144.png
old mode 100644
new mode 100755
index 698fb4a260b136..cbb055732f186a
Binary files a/app/javascript/icons/apple-touch-icon-144x144.png and b/app/javascript/icons/apple-touch-icon-144x144.png differ
diff --git a/app/javascript/icons/apple-touch-icon-152x152.png b/app/javascript/icons/apple-touch-icon-152x152.png
old mode 100644
new mode 100755
index 0cc93cc2888c02..3a7975c0541c75
Binary files a/app/javascript/icons/apple-touch-icon-152x152.png and b/app/javascript/icons/apple-touch-icon-152x152.png differ
diff --git a/app/javascript/icons/apple-touch-icon-167x167.png b/app/javascript/icons/apple-touch-icon-167x167.png
old mode 100644
new mode 100755
index 9bbbf53120cc00..25be4eb5f5bba5
Binary files a/app/javascript/icons/apple-touch-icon-167x167.png and b/app/javascript/icons/apple-touch-icon-167x167.png differ
diff --git a/app/javascript/icons/apple-touch-icon-180x180.png b/app/javascript/icons/apple-touch-icon-180x180.png
old mode 100644
new mode 100755
index 329b803b918992..dc0e9bc20b8086
Binary files a/app/javascript/icons/apple-touch-icon-180x180.png and b/app/javascript/icons/apple-touch-icon-180x180.png differ
diff --git a/app/javascript/icons/apple-touch-icon-57x57.png b/app/javascript/icons/apple-touch-icon-57x57.png
old mode 100644
new mode 100755
index e00e142c640eca..bb0dc957cd896b
Binary files a/app/javascript/icons/apple-touch-icon-57x57.png and b/app/javascript/icons/apple-touch-icon-57x57.png differ
diff --git a/app/javascript/icons/apple-touch-icon-60x60.png b/app/javascript/icons/apple-touch-icon-60x60.png
old mode 100644
new mode 100755
index 011285b564703b..9143a0bf07360d
Binary files a/app/javascript/icons/apple-touch-icon-60x60.png and b/app/javascript/icons/apple-touch-icon-60x60.png differ
diff --git a/app/javascript/icons/apple-touch-icon-72x72.png b/app/javascript/icons/apple-touch-icon-72x72.png
old mode 100644
new mode 100755
index 16679d5731a6d6..2b7d19484c9e3a
Binary files a/app/javascript/icons/apple-touch-icon-72x72.png and b/app/javascript/icons/apple-touch-icon-72x72.png differ
diff --git a/app/javascript/icons/apple-touch-icon-76x76.png b/app/javascript/icons/apple-touch-icon-76x76.png
old mode 100644
new mode 100755
index 83c87488768532..0985e33bcb20f7
Binary files a/app/javascript/icons/apple-touch-icon-76x76.png and b/app/javascript/icons/apple-touch-icon-76x76.png differ
diff --git a/app/javascript/icons/favicon-16x16.png b/app/javascript/icons/favicon-16x16.png
old mode 100644
new mode 100755
index eed8e0035c34b5..1326ba04627bcb
Binary files a/app/javascript/icons/favicon-16x16.png and b/app/javascript/icons/favicon-16x16.png differ
diff --git a/app/javascript/icons/favicon-32x32.png b/app/javascript/icons/favicon-32x32.png
old mode 100644
new mode 100755
index 9165746bcfa5f7..f5058cb0a56e41
Binary files a/app/javascript/icons/favicon-32x32.png and b/app/javascript/icons/favicon-32x32.png differ
diff --git a/app/javascript/icons/favicon-48x48.png b/app/javascript/icons/favicon-48x48.png
old mode 100644
new mode 100755
index 259676c0a9217e..6253d054c7f48f
Binary files a/app/javascript/icons/favicon-48x48.png and b/app/javascript/icons/favicon-48x48.png differ
diff --git a/app/javascript/mastodon/actions/antennas.js b/app/javascript/mastodon/actions/antennas.js
index 51002b6c5891cb..4716897586fe5e 100644
--- a/app/javascript/mastodon/actions/antennas.js
+++ b/app/javascript/mastodon/actions/antennas.js
@@ -236,10 +236,10 @@ export const createAntennaFail = error => ({
error,
});
-export const updateAntenna = (id, title, shouldReset, list_id, stl, with_media_only, ignore_reblog, insert_feeds) => (dispatch, getState) => {
+export const updateAntenna = (id, title, shouldReset, list_id, stl, ltl, with_media_only, ignore_reblog, insert_feeds) => (dispatch, getState) => {
dispatch(updateAntennaRequest(id));
- api(getState).put(`/api/v1/antennas/${id}`, { title, list_id, stl, with_media_only, ignore_reblog, insert_feeds }).then(({ data }) => {
+ api(getState).put(`/api/v1/antennas/${id}`, { title, list_id, stl, ltl, with_media_only, ignore_reblog, insert_feeds }).then(({ data }) => {
dispatch(updateAntennaSuccess(data));
if (shouldReset) {
diff --git a/app/javascript/mastodon/features/antenna_setting/index.jsx b/app/javascript/mastodon/features/antenna_setting/index.jsx
index 83f21fd066ec3b..086c1de6b63f84 100644
--- a/app/javascript/mastodon/features/antenna_setting/index.jsx
+++ b/app/javascript/mastodon/features/antenna_setting/index.jsx
@@ -198,31 +198,37 @@ class AntennaSetting extends PureComponent {
onStlToggle = ({ target }) => {
const { dispatch } = this.props;
const { id } = this.props.params;
- dispatch(updateAntenna(id, undefined, false, undefined, target.checked, undefined, undefined, undefined));
+ dispatch(updateAntenna(id, undefined, false, undefined, target.checked, undefined, undefined, undefined, undefined));
+ };
+
+ onLtlToggle = ({ target }) => {
+ const { dispatch } = this.props;
+ const { id } = this.props.params;
+ dispatch(updateAntenna(id, undefined, false, undefined, undefined, target.checked, undefined, undefined, undefined));
};
onMediaOnlyToggle = ({ target }) => {
const { dispatch } = this.props;
const { id } = this.props.params;
- dispatch(updateAntenna(id, undefined, false, undefined, undefined, target.checked, undefined, undefined));
+ dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, target.checked, undefined, undefined));
};
onIgnoreReblogToggle = ({ target }) => {
const { dispatch } = this.props;
const { id } = this.props.params;
- dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, target.checked, undefined));
+ dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, undefined, target.checked, undefined));
};
onNoInsertFeedsToggle = ({ target }) => {
const { dispatch } = this.props;
const { id } = this.props.params;
- dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, undefined, target.checked));
+ dispatch(updateAntenna(id, undefined, false, undefined, undefined, undefined, undefined, undefined, target.checked));
};
onSelect = value => {
const { dispatch } = this.props;
const { id } = this.props.params;
- dispatch(updateAntenna(id, undefined, false, value.value, undefined, undefined, undefined, undefined));
+ dispatch(updateAntenna(id, undefined, false, value.value, undefined, undefined, undefined, undefined, undefined));
};
onHomeSelect = () => this.onSelect({ value: '0' });
@@ -293,6 +299,7 @@ class AntennaSetting extends PureComponent {
const pinned = !!columnId;
const title = antenna ? antenna.get('title') : id;
const isStl = antenna ? antenna.get('stl') : undefined;
+ const isLtl = antenna ? antenna.get('ltl') : undefined;
const isMediaOnly = antenna ? antenna.get('with_media_only') : undefined;
const isIgnoreReblog = antenna ? antenna.get('ignore_reblog') : undefined;
const isInsertFeeds = antenna ? antenna.get('insert_feeds') : undefined;
@@ -312,7 +319,7 @@ class AntennaSetting extends PureComponent {
}
let columnSettings;
- if (!isStl) {
+ if (!isStl && !isLtl) {
columnSettings = (
<>
@@ -339,6 +346,12 @@ class AntennaSetting extends PureComponent {
);
+ } else if (isLtl) {
+ stlAlert = (
+
+ );
}
const rangeRadioValues = ImmutableList([
@@ -384,12 +397,23 @@ class AntennaSetting extends PureComponent {
-
-
-
-
+ {!isLtl && (
+
+
+
+
+ )}
+
+ {!isStl && (
+
+
+
+
+ )}
@@ -429,7 +453,7 @@ class AntennaSetting extends PureComponent {
>
)}
- {!isStl && (
+ {!isStl && !isLtl && (
<>
diff --git a/app/javascript/mastodon/features/lists/index.jsx b/app/javascript/mastodon/features/lists/index.jsx
index e947a40b83990d..fb52973d23d149 100644
--- a/app/javascript/mastodon/features/lists/index.jsx
+++ b/app/javascript/mastodon/features/lists/index.jsx
@@ -22,6 +22,7 @@ import NewListForm from './components/new_list_form';
const messages = defineMessages({
heading: { id: 'column.lists', defaultMessage: 'Lists' },
subheading: { id: 'lists.subheading', defaultMessage: 'Your lists' },
+ with_antenna: { id: 'lists.with_antenna', defaultMessage: 'Antenna' },
});
const getOrderedLists = createSelector([state => state.get('lists')], lists => {
@@ -76,7 +77,8 @@ class Lists extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{lists.map(list =>
- ,
+ ( 0) ? intl.formatMessage(messages.with_antenna) : undefined} />),
)}
diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
index 07e0980d213fcb..5b412ba14735f0 100644
--- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
@@ -7,7 +7,7 @@ import { Link } from 'react-router-dom';
import { WordmarkLogo } from 'mastodon/components/logo';
import NavigationPortal from 'mastodon/components/navigation_portal';
-import { enableDtlMenu, timelinePreview, trendsEnabled } from 'mastodon/initial_state';
+import { enableDtlMenu, timelinePreview, trendsEnabled, dtlTag } from 'mastodon/initial_state';
import { transientSingleColumn } from 'mastodon/is_mobile';
import ColumnLink from './column_link';
@@ -93,8 +93,8 @@ class NavigationPanel extends Component {
>
)}
- {signedIn && enableDtlMenu && (
-
+ {signedIn && enableDtlMenu && dtlTag && (
+
)}
{!signedIn && explorer}
diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js
index 356f7515b2bbd1..3e84866233aaf6 100644
--- a/app/javascript/mastodon/initial_state.js
+++ b/app/javascript/mastodon/initial_state.js
@@ -58,6 +58,7 @@
* @property {string} display_media
* @property {boolean} display_media_expand
* @property {string} domain
+ * @property {string} dtl_tag
* @property {boolean} enable_login_privacy
* @property {boolean} enable_dtl_menu
* @property {boolean=} expand_spoilers
@@ -124,6 +125,7 @@ export const disabledAccountId = getMeta('disabled_account_id');
export const displayMedia = getMeta('display_media');
export const displayMediaExpand = getMeta('display_media_expand');
export const domain = getMeta('domain');
+export const dtlTag = getMeta('dtl_tag');
export const enableLoginPrivacy = getMeta('enable_login_privacy');
export const enableDtlMenu = getMeta('enable_dtl_menu');
export const expandSpoilers = getMeta('expand_spoilers');
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 717b51443fd89a..a73bfe2d7e6727 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -206,7 +206,7 @@
"compose_form.direct_message_warning_learn_more": "ãã£ãšè©³ãã",
"compose_form.encryption_warning": "Mastodonã®æçš¿ã¯ãšã³ãããŒãšã³ãæå·åã«å¯Ÿå¿ããŠããŸãããå®å
šã«éåä¿¡ãããã¹ãæ
å ±ãMastodonã§å
±æããªãã§ãã ããã",
"compose_form.hashtag_warning": "ãã®æçš¿ã¯å
¬éèšå®ã§ã¯ãªãã®ã§ããã·ã¥ã¿ã°ã®äžèŠ§ã«è¡šç€ºãããŸãããå
¬éæçš¿ã ããããã·ã¥ã¿ã°ã§æ€çŽ¢ã§ããŸãã",
- "compose_form.limited_post_warning": "éå®æçš¿ã¯çŸç¶ãããäžéšã®MastodonãµãŒããŒã«ããå±ããŸããïŒ2023幎8ææç¹ã§FedibirdãkmyblueãPawooãªã©äžéšã®ã¿ã§ãïŒ",
+ "compose_form.limited_post_warning": "éå®æçš¿ã¯çŸç¶ãããäžéšã®MastodonãµãŒããŒã«ããå±ããŸããïŒ2023幎9ææç¹ã§Fedibirdãkmyblueãªã©äžéšã®ã¿ã§ãïŒ",
"compose_form.lock_disclaimer": "ããªãã®ã¢ã«ãŠã³ãã¯{locked}ã«ãªã£ãŠããŸããã誰ã§ãããªãããã©ããŒããããšãã§ãããã©ãã¯ãŒéå®ã®æçš¿ãèŠãããšãã§ããŸãã",
"compose_form.lock_disclaimer.lock": "æ¿èªå¶",
"compose_form.markdown.marked": "Markdownæå¹",
diff --git a/app/models/antenna.rb b/app/models/antenna.rb
index 29872be182594a..c14892e138bac4 100644
--- a/app/models/antenna.rb
+++ b/app/models/antenna.rb
@@ -25,6 +25,7 @@
# stl :boolean default(FALSE), not null
# ignore_reblog :boolean default(FALSE), not null
# insert_feeds :boolean default(FALSE), not null
+# ltl :boolean default(FALSE), not null
#
class Antenna < ApplicationRecord
include Expireable
@@ -45,16 +46,19 @@ class Antenna < ApplicationRecord
belongs_to :list, optional: true
scope :stls, -> { where(stl: true) }
+ scope :ltls, -> { where(ltl: true) }
scope :all_keywords, -> { where(any_keywords: true) }
scope :all_domains, -> { where(any_domains: true) }
scope :all_accounts, -> { where(any_accounts: true) }
scope :all_tags, -> { where(any_tags: true) }
scope :availables, -> { where(available: true).where(Arel.sql('any_keywords = FALSE OR any_domains = FALSE OR any_accounts = FALSE OR any_tags = FALSE')) }
scope :available_stls, -> { where(available: true, stl: true) }
+ scope :available_ltls, -> { where(available: true, stl: false, ltl: true) }
validate :list_owner
validate :validate_limit
validate :validate_stl_limit
+ validate :validate_ltl_limit
def list_owner
raise Mastodon::ValidationError, I18n.t('antennas.errors.invalid_list_owner') if !list_id.zero? && list.present? && list.account != account
@@ -235,6 +239,22 @@ def validate_stl_limit
stls = account.antennas.where(stl: true).where.not(id: id)
- errors.add(:base, I18n.t('antennas.errors.over_stl_limit', limit: 1)) if list_id.zero? ? stls.any? { |tl| tl.list_id.zero? } : stls.any? { |tl| tl.list_id != 0 }
+ errors.add(:base, I18n.t('antennas.errors.over_stl_limit', limit: 1)) if if insert_feeds
+ list_id.zero? ? stls.any? { |tl| tl.list_id.zero? } : stls.any? { |tl| tl.list_id != 0 }
+ else
+ stls.any? { |tl| !tl.insert_feeds }
+ end
+ end
+
+ def validate_ltl_limit
+ return unless ltl
+
+ ltls = account.antennas.where(ltl: true).where.not(id: id)
+
+ errors.add(:base, I18n.t('antennas.errors.over_ltl_limit', limit: 1)) if if insert_feeds
+ list_id.zero? ? ltls.any? { |tl| tl.list_id.zero? } : ltls.any? { |tl| tl.list_id != 0 }
+ else
+ ltls.any? { |tl| !tl.insert_feeds }
+ end
end
end
diff --git a/app/models/status.rb b/app/models/status.rb
index 786daa142c47f9..45e221d71c27a1 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -43,6 +43,7 @@ class Status < ApplicationRecord
include RateLimitable
include StatusSafeReblogInsert
include StatusSearchConcern
+ include DtlHelper
rate_limit by: :account, family: :statuses
@@ -291,7 +292,7 @@ def reported?
end
def dtl?
- tags.where(name: 'kmyblue').exists?
+ tags.where(name: DTL_TAG).exists?
end
def emojis
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index edc6bfe7136b85..45888d7572d32d 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -2,6 +2,7 @@
class InitialStateSerializer < ActiveModel::Serializer
include RoutingHelper
+ include DtlHelper
attributes :meta, :compose, :accounts,
:media_attachments, :settings,
@@ -35,6 +36,7 @@ def meta
trends_as_landing_page: Setting.trends_as_landing_page,
status_page_url: Setting.status_page_url,
sso_redirect: sso_redirect,
+ dtl_tag: DTL_ENABLED ? DTL_TAG : nil,
}
if object.current_account
diff --git a/app/serializers/rest/antenna_serializer.rb b/app/serializers/rest/antenna_serializer.rb
index 0d449a208931da..c0d03c7282f5c0 100644
--- a/app/serializers/rest/antenna_serializer.rb
+++ b/app/serializers/rest/antenna_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class REST::AntennaSerializer < ActiveModel::Serializer
- attributes :id, :title, :stl, :insert_feeds, :with_media_only, :ignore_reblog, :accounts_count, :domains_count, :tags_count, :keywords_count
+ attributes :id, :title, :stl, :ltl, :insert_feeds, :with_media_only, :ignore_reblog, :accounts_count, :domains_count, :tags_count, :keywords_count
class ListSerializer < ActiveModel::Serializer
attributes :id, :title
diff --git a/app/services/delivery_antenna_service.rb b/app/services/delivery_antenna_service.rb
index 9c4914515d7ab1..e494321917ce22 100644
--- a/app/services/delivery_antenna_service.rb
+++ b/app/services/delivery_antenna_service.rb
@@ -2,16 +2,21 @@
class DeliveryAntennaService
include FormattingHelper
+ include DtlHelper
- def call(status, update, stl_home)
+ def call(status, update, **options)
@status = status
@account = @status.account
@update = update
- if stl_home
- delivery_stl!
- else
+ mode = options[:mode] || :home
+ case mode
+ when :home
delivery!
+ when :stl
+ delivery_stl!
+ when :ltl
+ delivery_ltl!
end
end
@@ -19,6 +24,8 @@ def call(status, update, stl_home)
def delivery!
must_dtl_tag = @account.dissubscribable
+ return if must_dtl_tag && !DTL_ENABLED
+
tag_ids = @status.tags.pluck(:id)
domain = @account.domain || Rails.configuration.x.local_domain
follower_ids = @status.unlisted_visibility? ? @status.account.followers.pluck(:id) : []
@@ -31,7 +38,7 @@ def delivery!
antennas = Antenna.where(id: antennas.select(:id))
if must_dtl_tag
- dtl_tag = Tag.find_or_create_by_names('kmyblue').first
+ dtl_tag = Tag.find_or_create_by_names(DTL_TAG).first
return if !dtl_tag || tag_ids.exclude?(dtl_tag.id)
antennas = antennas.left_joins(:antenna_tags).where(antenna_tags: { tag_id: dtl_tag.id })
@@ -44,7 +51,7 @@ def delivery!
antennas = antennas.where(account: @status.mentioned_accounts) if @status.visibility.to_sym == :limited
antennas = antennas.where(with_media_only: false) unless @status.with_media?
antennas = antennas.where(ignore_reblog: false) if @status.reblog?
- antennas = antennas.where(stl: false)
+ antennas = antennas.where(stl: false, ltl: false)
collection = AntennaCollection.new(@status, @update, false)
content = extract_status_plain_text_with_spoiler_text(@status)
@@ -72,7 +79,8 @@ def delivery_stl!
antennas = antennas.where(account_id: Account.without_suspended.joins(:user).select('accounts.id').where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago))
home_post = !@account.domain.nil? || @status.reblog? || [:public, :public_unlisted, :login].exclude?(@status.visibility.to_sym)
- antennas = antennas.where(account: @account.followers).or(antennas.where(account: @account)).where.not(list_id: 0) if home_post
+ antennas = antennas.where(account: @account.followers).or(antennas.where(account: @account)).where('insert_feeds IS FALSE OR list_id > 0') if home_post && !@status.limited_visibility?
+ antennas = antennas.where(account: @status.mentioned_accounts).or(antennas.where(account: @account)).where('insert_feeds IS FALSE OR list_id > 0') if @status.limited_visibility?
collection = AntennaCollection.new(@status, @update, home_post)
@@ -87,6 +95,27 @@ def delivery_stl!
collection.deliver!
end
+ def delivery_ltl!
+ return if %i(public public_unlisted login).exclude?(@status.visibility.to_sym)
+ return unless @account.local?
+ return if @status.reblog?
+
+ antennas = Antenna.available_ltls
+ antennas = antennas.where(account_id: Account.without_suspended.joins(:user).select('accounts.id').where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago))
+
+ collection = AntennaCollection.new(@status, @update, false)
+
+ antennas.in_batches do |ans|
+ ans.each do |antenna|
+ next if antenna.expired?
+
+ collection.push(antenna)
+ end
+ end
+
+ collection.deliver!
+ end
+
class AntennaCollection
def initialize(status, update, stl_home = false) # rubocop:disable Style/OptionalBooleanParameter
@status = status
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index 156a811f51727f..a2e2653813ab4d 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -2,6 +2,7 @@
class FanOutOnWriteService < BaseService
include Redisable
+ include DtlHelper
# Push a status into home and mentions feeds
# @param [Status] status
@@ -51,11 +52,13 @@ def fan_out_to_local_recipients!
when :public, :unlisted, :public_unlisted, :login, :private
deliver_to_all_followers!
deliver_to_lists!
- deliver_to_antennas! if !@account.dissubscribable || (@status.dtl? && @account.user&.setting_dtl_force_subscribable && @status.tags.exists?(name: 'kmyblue'))
+ deliver_to_antennas! if !@account.dissubscribable || (@status.dtl? && DTL_ENABLED && @account.user&.setting_dtl_force_subscribable && @status.tags.exists?(name: DTL_TAG))
deliver_to_stl_antennas!
+ deliver_to_ltl_antennas!
when :limited
deliver_to_lists_mentioned_accounts_only!
deliver_to_antennas! unless @account.dissubscribable
+ deliver_to_stl_antennas!
deliver_to_mentioned_followers!
else
deliver_to_mentioned_followers!
@@ -135,11 +138,15 @@ def deliver_to_lists_mentioned_accounts_only!
end
def deliver_to_stl_antennas!
- DeliveryAntennaService.new.call(@status, @options[:update], true)
+ DeliveryAntennaService.new.call(@status, @options[:update], mode: :stl)
+ end
+
+ def deliver_to_ltl_antennas!
+ DeliveryAntennaService.new.call(@status, @options[:update], mode: :ltl)
end
def deliver_to_antennas!
- DeliveryAntennaService.new.call(@status, @options[:update], false)
+ DeliveryAntennaService.new.call(@status, @options[:update], mode: :home)
end
def deliver_to_mentioned_followers!
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index bd0e2a462aaf81..2e5b765d865f02 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -3,6 +3,7 @@
class PostStatusService < BaseService
include Redisable
include LanguagesHelper
+ include DtlHelper
MIN_SCHEDULE_OFFSET = 5.minutes.freeze
@@ -101,8 +102,10 @@ def load_circle
end
def overwrite_dtl_post
+ return unless DTL_ENABLED
+
raw_tags = Extractor.extract_hashtags(@text)
- return if raw_tags.exclude?('kmyblue')
+ return if raw_tags.exclude?(DTL_TAG)
return unless %i(public public_unlisted unlisted).include?(@visibility)
@visibility = :unlisted if @account.user&.setting_dtl_force_with_tag == :full
diff --git a/app/views/admin/ng_words/show.html.haml b/app/views/admin/ng_words/show.html.haml
index be8b56ac400a52..d76757e4c0d9fb 100644
--- a/app/views/admin/ng_words/show.html.haml
+++ b/app/views/admin/ng_words/show.html.haml
@@ -8,7 +8,7 @@
= render 'shared/error_messages', object: @admin_settings
.fields-group
- = f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords')
+ = f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint')
.fields-group
= f.input :post_hash_tags_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_hash_tags_max')
diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml
index 55bf9c6ddacc10..4ac61240418ebc 100644
--- a/app/views/settings/preferences/other/show.html.haml
+++ b/app/views/settings/preferences/other/show.html.haml
@@ -42,18 +42,20 @@
.fields-group
= ff.input :'web.enable_login_privacy', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_enable_login_privacy'), hint: false
- %h4= t 'preferences.dtl'
+ - if @dtl_enabled
- %p.hint= t 'preferences.dtl_hint'
+ %h4= t 'preferences.dtl'
- .fields-group
- = ff.input :'web.enable_dtl_menu', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_dtl_menu'), hint: I18n.t('simple_form.hints.defaults.setting_dtl_menu')
+ %p.hint= t 'preferences.dtl_hint', tag: @dtl_tag
- .fields-group
- = ff.input :dtl_force_with_tag, kmyblue: true, collection: ['full', 'searchability', 'none'], label_method: lambda { |item| safe_join([t("simple_form.labels.dtl_force_with_tag.#{item}")]) }, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: I18n.t('simple_form.labels.defaults.setting_dtl_force_with_tag'), hint: I18n.t('simple_form.hints.defaults.setting_dtl_force_with_tag')
+ .fields-group
+ = ff.input :'web.enable_dtl_menu', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_dtl_menu')
- .fields-group
- = ff.input :dtl_force_subscribable, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_dtl_force_subscribable'), hint: I18n.t('simple_form.hints.defaults.setting_dtl_force_subscribable')
+ .fields-group
+ = ff.input :dtl_force_with_tag, kmyblue: true, collection: ['full', 'searchability', 'none'], label_method: lambda { |item| safe_join([t("simple_form.labels.dtl_force_with_tag.#{item}")]) }, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: I18n.t('simple_form.labels.defaults.setting_dtl_force_with_tag'), hint: I18n.t('simple_form.hints.defaults.setting_dtl_force_with_tag', tag: @dtl_tag)
+
+ .fields-group
+ = ff.input :dtl_force_subscribable, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_dtl_force_subscribable'), hint: I18n.t('simple_form.hints.defaults.setting_dtl_force_subscribable')
%h4= t 'preferences.public_timelines'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 9f87e2c6c462d7..b05633ad47935e 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -600,6 +600,7 @@ en:
enable_block_emoji_reaction_settings: Enable block emoji reactions settings for users
hide_local_users_for_anonymous: Hide timeline local user posts from anonymous
keywords: Reject keywords
+ keywords_hint: The first character of the line is "?". to use regular expressions
post_hash_tags_max: Hash tags max for posts
test_error: Testing is returned any errors
title: NG words and against spams
@@ -780,6 +781,7 @@ en:
hint: This keywords is applied to public posts only..
keywords: Sensitive keywords
keywords_for_all: Sensitive keywords (Contains CW alert)
+ keywords_for_all_hint: The first character of the line is "?". to use regular expressions
title: Sensitive words and moderation options
settings:
about:
@@ -1111,6 +1113,7 @@ en:
invalid_context: None or invalid context supplied
invalid_list_owner: This list is not yours
over_limit: You have exceeded the limit of %{limit} antennas
+ over_ltl_limit: You have exceeded the limit of %{limit} ltl antennas
over_stl_limit: You have exceeded the limit of %{limit} stl antennas
index:
contexts: Antennas in %{contexts}
@@ -1642,7 +1645,7 @@ en:
too_many_options: can't contain more than %{max} items
preferences:
dtl: Deep timeline
- dtl_hint: "You can join deep timeline with #kmyblue tag. Following settings make convenient to use deep timeline."
+ dtl_hint: "You can join deep timeline with #%{tag} tag. Following settings make convenient to use deep timeline."
other: Other
posting_defaults: Posting defaults
public_timelines: Public timelines
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index f219a97112a799..0b36b6dc423929 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -598,6 +598,7 @@ ja:
enable_block_emoji_reaction_settings: åãŠãŒã¶ãŒã«ã¹ã¿ã³ãæ©èœã®ãããã¯èšå®é
ç®ã解æŸãã
hide_local_users_for_anonymous: ãã°ã€ã³ããŠããªãç¶æ
ã§ããŒã«ã«ãŠãŒã¶ãŒã®æçš¿ãã¿ã€ã ã©ã€ã³ããååŸã§ããªãããã«ãã
keywords: æçš¿ã§ããªãããŒã¯ãŒã
+ keywords_hint: è¡ãã?ãã§å§ãããšãæ£èŠè¡šçŸã䜿ããŸã
post_hash_tags_max: æçš¿ã«èšå®å¯èœãªããã·ã¥ã¿ã°ã®æ倧æ°
test_error: NGã¯ãŒãã®ãã¹ãã«å€±æããŸãããæ£èŠè¡šçŸã®ãã¹ãå«ãŸããŠãããããããŸãã
title: NGã¯ãŒããšã¹ãã
@@ -775,7 +776,7 @@ ja:
hint: ã»ã³ã·ãã£ããªããŒã¯ãŒãã®èšå®ã¯ãåœãµãŒããŒã®ããŒã«ã«ãŠãŒã¶ãŒã«ããå
¬éç¯å²ãå
¬éããããŒã«ã«å
¬éãããã°ã€ã³ãŠãŒã¶ãŒã®ã¿ãã«å¯ŸããŠé©çšãããŸãã
keywords: ã»ã³ã·ãã£ããªããŒã¯ãŒãïŒèŠåæã¯é€å€ïŒ
keywords_for_all: ã»ã³ã·ãã£ããªããŒã¯ãŒãïŒèŠåæã«ãé©çšïŒ
- keywords_for_all_hint: ããã§æå®ããããŒã¯ãŒããå«ãæçš¿ã¯åŒ·å¶çã«CWã«ãªããŸããèŠåæã«ãå«ãŸããŠããã°CWã«ãªããŸã
+ keywords_for_all_hint: ããã§æå®ããããŒã¯ãŒããå«ãæçš¿ã¯åŒ·å¶çã«CWã«ãªããŸããèŠåæã«ãå«ãŸããŠããã°CWã«ãªããŸããè¡ãã?ãã§å§ãŸã£ãŠããã°æ£èŠè¡šçŸã䜿ããŸã
keywords_hint: ããã§æå®ããããŒã¯ãŒããå«ãæçš¿ã¯åŒ·å¶çã«CWã«ãªããŸãããã ãèŠåæã«äœ¿çšããŠããå Žåã¯ç¡èŠãããŸã
title: ã»ã³ã·ãã£ãåèªãšèšå®
settings:
@@ -1031,6 +1032,7 @@ ja:
keywords: ç»é²ã§ããããŒã¯ãŒãæ°ã®äžéã«éããŠããŸã
tags: ç»é²ã§ããã¿ã°æ°ã®äžéã«éããŠããŸã
over_limit: ææã§ããã¢ã³ããæ° %{limit}ãè¶
ããŠããŸã
+ over_ltl_limit: ææã§ããLTLã¢ãŒãä»ãã¢ã³ããæ° (ããŒã /ãªã¹ãããããã«ã€ã%{limit}) ãè¶
ããŠããŸã
over_stl_limit: ææã§ããSTLã¢ãŒãä»ãã¢ã³ããæ° (ããŒã /ãªã¹ãããããã«ã€ã%{limit}) ãè¶
ããŠããŸã
too_short_keyword: ããŒã¯ãŒããçãããŸã
edit:
@@ -1108,7 +1110,7 @@ ja:
help_html: CAPTCHAã®è§£æ±ºã«åé¡ãããå Žåã¯ã %{email} ãŸã§ãåãåãããã ããããæäŒãããããŸãã
hint_html: ããäžã€ã ãïŒããªãã人éã§ããããšã確èªããå¿
èŠããããŸã(ã¹ãã ãé²ãããã§ãïŒ)ã 以äžã®CAPTCHAã解ãããç¶ããããã¯ãªãã¯ããŸãã
title: ã»ãã¥ãªãã£ãã§ãã¯
- cloudflare_with_registering: ç»é²æã«Cloudflareã®ç»é¢ã衚瀺ãããŸããç»é²ã§ããªããšã㯠tt@kmycode.net ãŸã§ãé£çµ¡ãã ãã
+ cloudflare_with_registering: ç»é²æã«Cloudflareã®ç»é¢ã衚瀺ãããŸããç»é²ã§ããªããšãã¯ç®¡çè
ãžãé£çµ¡ãã ãã
confirmations:
wrong_email_hint: ã¡ãŒã«ã¢ãã¬ã¹ãæ£ãããªãå Žåã¯ãã¢ã«ãŠã³ãèšå®ã§å€æŽã§ããŸãã
delete_account: ã¢ã«ãŠã³ãã®åé€
@@ -1583,7 +1585,7 @@ ja:
too_many_options: ã¯%{max}åãŸã§ã§ã
preferences:
dtl: ãã£ãŒãã¿ã€ã ã©ã€ã³
- dtl_hint: "#kmyblue ããã·ã¥ã¿ã°ã«åå ããããšã§ããã£ãŒãã¿ã€ã ã©ã€ã³ã«æçš¿ã§ããŸããããã§ã¯ãã£ãŒãã¿ã€ã ã©ã€ã³ãå©çšããããããããã®èšå®ãã§ããŸãã"
+ dtl_hint: "#%{tag} ããã·ã¥ã¿ã°ã«åå ããããšã§ããã£ãŒãã¿ã€ã ã©ã€ã³ã«æçš¿ã§ããŸããããã§ã¯ãã£ãŒãã¿ã€ã ã©ã€ã³ãå©çšããããããããã®èšå®ãã§ããŸãã"
other: ãã®ä»
posting_defaults: ããã©ã«ãã®æçš¿èšå®
public_timelines: å
¬éã¿ã€ã ã©ã€ã³
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 24d5981302b986..4a927ea211c1e2 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -67,7 +67,7 @@ en:
setting_display_media_hide_all: Always hide media
setting_display_media_show_all: Always show media
setting_dtl_force_subscribable: Your post can be detected local user's antenna to subscribe deep timeline
- setting_dtl_force_with_tag: "With using #kmyblue tag, your post settings will be changed forcibly"
+ setting_dtl_force_with_tag: "With using #%{tag} tag, your post settings will be changed forcibly"
setting_dtl_menu: Show DTL menu on web
setting_use_blurhash: Gradients are based on the colors of the hidden visuals but obfuscate any details
setting_use_pending_items: Hide timeline updates behind a click instead of automatically scrolling the feed
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index ccda4fa8cf4b18..699173a95119ec 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -69,7 +69,7 @@ ja:
setting_display_media_hide_all: ã¡ãã£ã¢ãåžžã«é ã
setting_display_media_show_all: ã¡ãã£ã¢ãåžžã«è¡šç€ºãã
setting_dtl_force_subscribable: 賌èªæåŠèšå®ã«é¢ä¿ãªãããã£ãŒãã¿ã€ã ã©ã€ã³ã«åããæçš¿ã¯ã¢ã³ããã«æ²èŒãããŸãããã£ãŒãã¿ã€ã ã©ã€ã³ãã¢ã³ããçµç±ã§é²èŠ§ããŠãã人ã«ããªãã®çºèšãå±ããŸã
- setting_dtl_force_with_tag: "ããã·ã¥ã¿ã° #kmyblue ãã€ããŠæçš¿ãããšããå
¬éç¯å²ãšæ€çŽ¢èš±å¯ã匷å¶çã«çœ®ãæããããèšå®ããŸã"
+ setting_dtl_force_with_tag: "ããã·ã¥ã¿ã° #%{tag} ãã€ããŠæçš¿ãããšããå
¬éç¯å²ãšæ€çŽ¢èš±å¯ã匷å¶çã«çœ®ãæããããèšå®ããŸã"
setting_emoji_reaction_streaming_notify_impl2: åœè©²ãµãŒããŒã®ç¬èªæ©èœã«å¯Ÿå¿ããã¢ããªãå©çšæã«ãã¹ã¿ã³ãæ©èœãå©çšã§ããŸããåäœç¢ºèªããŠããªãããïŒãããããã®ãããªã¢ããªèªäœã確èªã§ããŠããªãããïŒæ£ããåããªãå ŽåããããŸã
setting_hide_network: ãã©ããŒãšãã©ãã¯ãŒã®æ
å ±ããããã£ãŒã«ããŒãžã§èŠãããªãããã«ããŸã
setting_link_preview: ãã¬ãã¥ãŒçæãåæ¢ããããšã¯ãã»ã³ã·ãã£ããªãµã€ããžã®ãªã³ã¯ãé »ç¹ã«æçš¿ãã人ã«ãæå¹ãããããŸãã
diff --git a/db/migrate/20230911022527_add_ltl_to_antennas.rb b/db/migrate/20230911022527_add_ltl_to_antennas.rb
new file mode 100644
index 00000000000000..18eeb19a3ccde1
--- /dev/null
+++ b/db/migrate/20230911022527_add_ltl_to_antennas.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require Rails.root.join('lib', 'mastodon', 'migration_helpers')
+
+class AddLtlToAntennas < ActiveRecord::Migration[7.0]
+ include Mastodon::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def change
+ safety_assured do
+ add_column_with_default :antennas, :ltl, :boolean, default: false, allow_null: false
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 1ade0757828a37..f322d5e715336d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2023_09_07_150100) do
+ActiveRecord::Schema[7.0].define(version: 2023_09_11_022527) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -50,6 +50,15 @@
t.index ["account_id", "domain"], name: "index_account_domain_blocks_on_account_id_and_domain", unique: true
end
+ create_table "account_groups", force: :cascade do |t|
+ t.bigint "account_id", null: false
+ t.bigint "group_account_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["account_id"], name: "index_account_groups_on_account_id"
+ t.index ["group_account_id"], name: "index_account_groups_on_group_account_id"
+ end
+
create_table "account_migrations", force: :cascade do |t|
t.bigint "account_id"
t.string "acct", default: "", null: false
@@ -313,6 +322,7 @@
t.boolean "stl", default: false, null: false
t.boolean "ignore_reblog", default: false, null: false
t.boolean "insert_feeds", default: false, null: false
+ t.boolean "ltl", default: false, null: false
t.index ["account_id"], name: "index_antennas_on_account_id"
t.index ["any_accounts"], name: "index_antennas_on_any_accounts"
t.index ["any_domains"], name: "index_antennas_on_any_domains"
@@ -1357,6 +1367,7 @@
add_foreign_key "account_conversations", "conversations", on_delete: :cascade
add_foreign_key "account_deletion_requests", "accounts", on_delete: :cascade
add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade
+ add_foreign_key "account_groups", "accounts", on_delete: :cascade
add_foreign_key "account_migrations", "accounts", column: "target_account_id", on_delete: :nullify
add_foreign_key "account_migrations", "accounts", on_delete: :cascade
add_foreign_key "account_moderation_notes", "accounts"
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index fac76c2045ef22..c00ed740a2b4f7 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -4,6 +4,14 @@ module Mastodon
module Version
module_function
+ def kmyblue_major
+ 3
+ end
+
+ def kmyblue_minor
+ 0
+ end
+
def major
4
end
@@ -24,8 +32,17 @@ def prerelease
ENV['MASTODON_VERSION_PRERELEASE'].presence || default_prerelease
end
+ def to_a_of_kmyblue
+ [kmyblue_major, kmyblue_minor].compact
+ end
+
+ def to_s_of_kmyblue
+ components = [to_a_of_kmyblue.join('.')]
+ components.join
+ end
+
def build_metadata
- ENV.fetch('MASTODON_VERSION_METADATA', nil)
+ ['kmyblue', to_s_of_kmyblue, ENV.fetch('MASTODON_VERSION_METADATA', nil)].compact.join('.')
end
def to_a
diff --git a/public/favicon.ico b/public/favicon.ico
old mode 100644
new mode 100755
index b09a98bb9b0649..fc5e475d425f5e
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb
index 84e2c91a85dfd4..0b8825135d1f68 100644
--- a/spec/models/concerns/account_interactions_spec.rb
+++ b/spec/models/concerns/account_interactions_spec.rb
@@ -9,6 +9,8 @@
let(:target_account) { Fabricate(:account, username: 'target') }
let(:target_account_id) { target_account.id }
let(:target_account_ids) { [target_account_id] }
+ let(:follower_account) { Fabricate(:account, username: 'follower') }
+ let(:followee_account) { Fabricate(:account, username: 'followee') }
describe '.following_map' do
subject { Account.following_map(target_account_ids, account_id) }
@@ -711,4 +713,20 @@
expect(account.lists_for_local_distribution.to_a).to contain_exactly(follower_list, self_list)
end
end
+
+ describe '#mutuals' do
+ subject { account.mutuals }
+
+ context 'when following target_account' do
+ it 'mutual one' do
+ account.follow!(target_account)
+ target_account.follow!(account)
+ follower_account.follow!(account)
+ account.follow!(followee_account)
+
+ expect(subject.count).to eq 1
+ expect(subject.first.id).to eq target_account.id
+ end
+ end
+ end
end
diff --git a/spec/services/delivery_antenna_service_spec.rb b/spec/services/delivery_antenna_service_spec.rb
index 961ccc6a5c0bc8..aa63aed74cb8d3 100644
--- a/spec/services/delivery_antenna_service_spec.rb
+++ b/spec/services/delivery_antenna_service_spec.rb
@@ -27,7 +27,7 @@
let!(:antenna) { nil }
let!(:empty_antenna) { nil }
- let(:stl_home) { false }
+ let(:mode) { :home }
before do
bob.follow!(alice)
@@ -35,7 +35,7 @@
allow(redis).to receive(:publish)
- subject.call(status, false, stl_home)
+ subject.call(status, false, mode: mode)
end
def home_feed_of(account)
@@ -323,4 +323,40 @@ def list(owner)
end
end
end
+
+ context 'when stl mode keyword is not working' do
+ let(:mode) { :stl }
+ let!(:antenna) { antenna_with_keyword(bob, 'anime', stl: true) }
+
+ it 'detecting antenna' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ end
+ end
+
+ context 'when ltl mode keyword is not working' do
+ let(:mode) { :ltl }
+ let!(:antenna) { antenna_with_keyword(bob, 'anime', ltl: true) }
+
+ it 'detecting antenna' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ end
+ end
+
+ context 'when stl mode exclude_keyword is not working' do
+ let(:mode) { :stl }
+ let!(:antenna) { antenna_with_keyword(bob, 'anime', exclude_keywords: ['body'], stl: true) }
+
+ it 'detecting antenna' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ end
+ end
+
+ context 'when ltl mode exclude_keyword is not working' do
+ let(:mode) { :ltl }
+ let!(:antenna) { antenna_with_keyword(bob, 'anime', exclude_keywords: ['body'], ltl: true) }
+
+ it 'detecting antenna' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ end
+ end
end
diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb
index e3d8c952dc2840..c15253c879cb5b 100644
--- a/spec/services/fan_out_on_write_service_spec.rb
+++ b/spec/services/fan_out_on_write_service_spec.rb
@@ -56,6 +56,10 @@ def antenna_with_account(owner, target_account)
antenna
end
+ def antenna_with_options(owner, **options)
+ Fabricate(:antenna, account: owner, **options)
+ end
+
context 'when status is public' do
let(:visibility) { 'public' }
@@ -97,6 +101,26 @@ def antenna_with_account(owner, target_account)
expect(antenna_feed_of(empty_antenna)).to_not include status.id
end
end
+
+ context 'with STL antenna' do
+ let!(:antenna) { antenna_with_options(bob, stl: true) }
+ let!(:empty_antenna) { antenna_with_options(tom) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
+
+ context 'with LTL antenna' do
+ let!(:antenna) { antenna_with_options(bob, ltl: true) }
+ let!(:empty_antenna) { antenna_with_options(tom) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
end
context 'when status is limited' do
@@ -138,6 +162,24 @@ def antenna_with_account(owner, target_account)
expect(antenna_feed_of(empty_antenna)).to_not include status.id
end
end
+
+ context 'with STL antenna' do
+ let!(:antenna) { antenna_with_options(bob, stl: true) }
+ let!(:empty_antenna) { antenna_with_options(tom, stl: true) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
+
+ context 'with LTL antenna' do
+ let!(:empty_antenna) { antenna_with_options(bob, ltl: true) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
end
context 'when status is private' do
@@ -176,6 +218,24 @@ def antenna_with_account(owner, target_account)
expect(antenna_feed_of(empty_antenna)).to_not include status.id
end
end
+
+ context 'with STL antenna' do
+ let!(:antenna) { antenna_with_options(bob, stl: true) }
+ let!(:empty_antenna) { antenna_with_options(ohagi, stl: true) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
+
+ context 'with LTL antenna' do
+ let!(:empty_antenna) { antenna_with_options(bob, ltl: true) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
end
context 'when status is unlisted' do
@@ -215,6 +275,24 @@ def antenna_with_account(owner, target_account)
end
end
+ context 'with STL antenna' do
+ let!(:antenna) { antenna_with_options(bob, stl: true) }
+ let!(:empty_antenna) { antenna_with_options(ohagi, stl: true) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(antenna)).to include status.id
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
+
+ context 'with LTL antenna' do
+ let!(:empty_antenna) { antenna_with_options(bob, ltl: true) }
+
+ it 'is added to the antenna feed of antenna follower' do
+ expect(antenna_feed_of(empty_antenna)).to_not include status.id
+ end
+ end
+
context 'with non-public searchability' do
let(:searchability) { 'direct' }
diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb
index 91fee989ab7f25..3b953b9fc1fb65 100644
--- a/spec/services/post_status_service_spec.rb
+++ b/spec/services/post_status_service_spec.rb
@@ -173,12 +173,37 @@
it 'mutual visibility' do
account = Fabricate(:account)
+ mutual_account = Fabricate(:account)
+ other_account = Fabricate(:account)
text = 'This is an English text.'
+ mutual_account.follow!(account)
+ account.follow!(mutual_account)
+ other_account.follow!(account)
status = subject.call(account, text: text, visibility: 'mutual')
expect(status.visibility).to eq 'limited'
expect(status.limited_scope).to eq 'mutual'
+ expect(status.mentioned_accounts.count).to eq 1
+ expect(status.mentioned_accounts.first.id).to eq mutual_account.id
+ end
+
+ it 'circle visibility' do
+ account = Fabricate(:account)
+ circle_account = Fabricate(:account)
+ other_account = Fabricate(:account)
+ circle = Fabricate(:circle, account: account)
+ text = 'This is an English text.'
+
+ circle_account.follow!(account)
+ other_account.follow!(account)
+ circle.accounts << circle_account
+ status = subject.call(account, text: text, visibility: 'circle', circle_id: circle.id)
+
+ expect(status.visibility).to eq 'limited'
+ expect(status.limited_scope).to eq 'circle'
+ expect(status.mentioned_accounts.count).to eq 1
+ expect(status.mentioned_accounts.first.id).to eq circle_account.id
end
it 'safeguards mentions' do