Merge remote-tracking branch 'parent/main' into kb_development

This commit is contained in:
KMY 2023-12-09 10:04:10 +09:00
commit f20cb3fd59
60 changed files with 1036 additions and 695 deletions

View file

@ -120,7 +120,6 @@ module.exports = defineConfig({
'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/jsx-wrap-multilines': 'error',
'react/no-deprecated': 'off',
'react/no-unknown-property': 'off',
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/self-closing-comp': 'error',

View file

@ -50,7 +50,6 @@
matchManagers: ['bundler'],
matchPackageNames: [
'rack', // Needs to be synced with Rails version
'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x
'strong_migrations', // Requires manual upgrade
'sidekiq', // Requires manual upgrade
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version

View file

@ -5,7 +5,7 @@ ruby '>= 3.0.0'
gem 'puma', '~> 6.3'
gem 'rails', '~> 7.1.1'
gem 'sprockets', '~> 3.7.2'
gem 'propshaft'
gem 'thor', '~> 1.2'
gem 'rack', '~> 2.2.7'
@ -89,7 +89,6 @@ gem 'sidekiq-unique-jobs', '~> 7.1'
gem 'sidekiq-bulk', '~> 0.2.0'
gem 'simple-navigation', '~> 4.4'
gem 'simple_form', '~> 5.2'
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
gem 'stoplight', '~> 3.0.1'
gem 'strong_migrations', '1.6.4'
gem 'tty-prompt', '~> 0.23', require: false

View file

@ -197,7 +197,7 @@ GEM
activesupport
cbor (0.5.9.6)
charlock_holmes (0.7.7)
chewy (7.3.4)
chewy (7.3.5)
activesupport (>= 5.2)
elasticsearch (>= 7.12.0, < 7.14.0)
elasticsearch-dsl
@ -377,7 +377,7 @@ GEM
terminal-table (>= 1.5.1)
idn-ruby (0.1.5)
io-console (0.6.0)
irb (1.10.0)
irb (1.10.1)
rdoc
reline (>= 0.3.8)
jmespath (1.6.2)
@ -484,7 +484,8 @@ GEM
nokogiri (1.15.5)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
oj (3.16.1)
oj (3.16.2)
bigdecimal (~> 3.1)
omniauth (2.1.1)
hashie (>= 3.4.6)
rack (>= 2.2.3)
@ -534,6 +535,11 @@ GEM
net-smtp
premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0)
propshaft (0.8.0)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.1.1.1)
stringio
public_suffix (5.0.4)
@ -608,7 +614,7 @@ GEM
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.6.1)
rdf (~> 3.2)
rdoc (6.6.0)
rdoc (6.6.1)
psych (>= 4.0.0)
redcarpet (3.6.0)
redis (4.8.1)
@ -704,7 +710,7 @@ GEM
scenic (1.7.0)
activerecord (>= 4.0.0)
railties (>= 4.0.0)
selenium-webdriver (4.15.0)
selenium-webdriver (4.16.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
@ -738,13 +744,6 @@ GEM
simplecov-lcov (0.8.0)
simplecov_json_formatter (0.1.4)
smart_properties (1.17.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
stackprof (0.2.25)
statsd-ruby (1.5.0)
stoplight (3.0.2)
@ -913,6 +912,7 @@ DEPENDENCIES
posix-spawn
premailer-rails
private_address_check (~> 0.5)
propshaft
public_suffix (~> 5.0)
puma (~> 6.3)
pundit (~> 2.3)
@ -952,8 +952,6 @@ DEPENDENCIES
simple_form (~> 5.2)
simplecov (~> 0.22)
simplecov-lcov (~> 0.8)
sprockets (~> 3.7.2)
sprockets-rails (~> 3.4)
stackprof
stoplight (~> 3.0.1)
strong_migrations (= 1.6.4)

View file

@ -299,9 +299,9 @@ class LoginForm extends React.PureComponent {
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onKeyDown={this.handleKeyDown}
autocomplete='off'
autocapitalize='off'
spellcheck='false'
autoComplete='off'
autoCapitalize='off'
spellCheck='false'
/>
<Button onClick={this.handleSubmit} disabled={isSubmitting || error}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>

View file

@ -99,7 +99,7 @@ class NavigationPanel extends Component {
</div>
{banner &&
<div class='navigation-panel__banner'>
<div className='navigation-panel__banner'>
{banner}
</div>
}

View file

@ -612,7 +612,6 @@ class Video extends PureComponent {
aria-label={alt}
title={alt}
lang={lang}
volume={volume}
onClick={this.togglePlay}
onKeyDown={this.handleVideoKeyDown}
onPlay={this.handlePlay}

View file

@ -702,7 +702,7 @@
"timeline_hint.resources.followers": "Les abonnés",
"timeline_hint.resources.follows": "Les abonnements",
"timeline_hint.resources.statuses": "Messages plus anciens",
"trends.counter_by_accounts": "{count, plural, one {{counter} personne} other {{counter} personnes}} au cours {days, plural, one {des dernières 24h} other {des {days} derniers jours}}",
"trends.counter_by_accounts": "{count, plural, one {{counter} pers.} other {{counter} pers.}} sur {days, plural, one {les dernières 24h} other {les {days} derniers jours}}",
"trends.trending_now": "Tendance en ce moment",
"ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
"units.short.billion": "{count}Md",

View file

@ -13,7 +13,7 @@
"about.rules": "Kiszolgáló szabályai",
"account.account_note_header": "Feljegyzés",
"account.add_or_remove_from_list": "Hozzáadás vagy eltávolítás a listákról",
"account.badges.bot": "Bot",
"account.badges.bot": "Automatizált",
"account.badges.group": "Csoport",
"account.block": "@{name} letiltása",
"account.block_domain": "Domain blokkolása: {domain}",
@ -63,8 +63,8 @@
"account.share": "@{name} profiljának megosztása",
"account.show_reblogs": "@{name} megtolásainak mutatása",
"account.statuses_counter": "{count, plural, one {{counter} Bejegyzés} other {{counter} Bejegyzés}}",
"account.unblock": "@{name} tiltásának feloldása",
"account.unblock_domain": "{domain} domain tiltás feloldása",
"account.unblock": "@{name} letiltásának feloldása",
"account.unblock_domain": "{domain} domain tiltásának feloldása",
"account.unblock_short": "Tiltás feloldása",
"account.unendorse": "Ne jelenjen meg a profilodon",
"account.unfollow": "Követés megszüntetése",
@ -138,21 +138,21 @@
"compose.language.search": "Nyelv keresése...",
"compose.published.body": "A bejegyzés publikálásra került.",
"compose.published.open": "Megnyitás",
"compose.saved.body": "A bejegyzés mentésre került.",
"compose.saved.body": "A bejegyzés mentve.",
"compose_form.direct_message_warning_learn_more": "Tudj meg többet",
"compose_form.encryption_warning": "A bejegyzések Mastodonon nem használnak végpontok közötti titkosítást. Ne ossz meg semmilyen érzékeny információt Mastodonon.",
"compose_form.encryption_warning": "A bejegyzések a Mastodonon nem használnak végpontok közti titkosítást. Ne ossz meg semmilyen érzékeny információt a Mastodonon.",
"compose_form.hashtag_warning": "Ez a bejegyzésed nem fog megjelenni semmilyen hashtag alatt, mivel nem nyilvános. Csak a nyilvános bejegyzések kereshetők hashtaggel.",
"compose_form.lock_disclaimer": "A fiókod nincs {locked}. Bárki követni tud, hogy megtekintse a kizárólag követőknek szánt bejegyzéseket.",
"compose_form.lock_disclaimer.lock": "lezárva",
"compose_form.lock_disclaimer.lock": "zárolva",
"compose_form.placeholder": "Mi jár a fejedben?",
"compose_form.poll.add_option": "Lehetőség hozzáadása",
"compose_form.poll.duration": "Szavazás időtartama",
"compose_form.poll.option_placeholder": "{number}. lehetőség",
"compose_form.poll.remove_option": "Lehetőség törlése",
"compose_form.poll.remove_option": "Lehetőség eltávolítása",
"compose_form.poll.switch_to_multiple": "Szavazás megváltoztatása több választásosra",
"compose_form.poll.switch_to_single": "Szavazás megváltoztatása egyetlen választásosra",
"compose_form.publish": "Közzététel",
"compose_form.publish_form": "Közzététel",
"compose_form.publish_form": "Új bejegyzés",
"compose_form.publish_loud": "{publish}!",
"compose_form.save_changes": "Módosítások mentése",
"compose_form.sensitive.hide": "{count, plural, one {Média kényesnek jelölése} other {Média kényesnek jelölése}}",
@ -195,13 +195,13 @@
"copy_icon_button.copied": "A szöveg a vágólapra másolva",
"copypaste.copied": "Másolva",
"copypaste.copy_to_clipboard": "Másolás vágólapra",
"directory.federated": "Az ismert fediverzumból",
"directory.federated": "Az ismert födiverzumból",
"directory.local": "Csak {domain} tartományból",
"directory.new_arrivals": "Új csatlakozók",
"directory.recently_active": "Nemrég aktív",
"disabled_account_banner.account_settings": "Fiókbeállítások",
"disabled_account_banner.text": "A(z) {disabledAccount} fiókod jelenleg le van tiltva.",
"dismissable_banner.community_timeline": "Ezek a legfrissebb nyilvános bejegyzések, amelyeket {domain} tartományban levő kiszolgáló fiókjait használó emberek tettek közzé.",
"dismissable_banner.community_timeline": "Ezek a legfrissebb nyilvános bejegyzések, amelyeket a(z) {domain} kiszolgáló fiókjait használó emberek tették közzé.",
"dismissable_banner.dismiss": "Elvetés",
"dismissable_banner.explore_links": "Jelenleg ezekről a hírekről beszélgetnek az ezen és a központosítás nélküli hálózat többi kiszolgálóján lévő emberek.",
"dismissable_banner.explore_statuses": "Ezek jelenleg népszerűvé váló bejegyzések a háló különböző szegleteiből. Az újabb vagy több megtolással rendelkező bejegyzéseket, illetve a kedvencnek jelöléssel rendelkezőeket rangsoroljuk előrébb.",
@ -216,14 +216,14 @@
"emoji_button.food": "Étel és Ital",
"emoji_button.label": "Emodzsi beszúrása",
"emoji_button.nature": "Természet",
"emoji_button.not_found": "Nincsenek emodzsik!! (╯°□°)╯︵ ┻━┻",
"emoji_button.not_found": "Nem találhatók emodzsik",
"emoji_button.objects": "Tárgyak",
"emoji_button.people": "Emberek",
"emoji_button.recent": "Gyakran használt",
"emoji_button.search": "Keresés...",
"emoji_button.search_results": "Keresési találatok",
"emoji_button.symbols": "Szimbólumok",
"emoji_button.travel": "Utazás és Helyek",
"emoji_button.travel": "Utazás és helyek",
"empty_column.account_hides_collections": "Ez a felhasználó úgy döntött, hogy nem teszi elérhetővé ezt az információt.",
"empty_column.account_suspended": "Fiók felfüggesztve",
"empty_column.account_timeline": "Itt nincs bejegyzés!",
@ -245,7 +245,7 @@
"empty_column.mutes": "Még egy felhasználót sem némítottál le.",
"empty_column.notifications": "Jelenleg még nincsenek értesítéseid. Ha mások kapcsolatba lépnek veled, ezek itt lesznek láthatóak.",
"empty_column.public": "Jelenleg itt nincs semmi! Írj valamit nyilvánosan vagy kövess más kiszolgálón levő felhasználókat, hogy megtöltsd.",
"error.unexpected_crash.explanation": "Egy hiba vagy böngésző inkompatibilitás miatt ez az oldal nem jeleníthető meg rendesen.",
"error.unexpected_crash.explanation": "Egy kód- vagy böngészőkompatibilitási hiba miatt ez az oldal nem jeleníthető meg helyesen.",
"error.unexpected_crash.explanation_addons": "Ezt az oldalt nem lehet helyesen megjeleníteni. Ezt a hibát valószínűleg egy böngésző kiegészítő vagy egy automatikus fordító okozza.",
"error.unexpected_crash.next_steps": "Próbáld frissíteni az oldalt. Ha ez nem segít, egy másik böngészőn vagy appon keresztül még mindig használhatod a Mastodont.",
"error.unexpected_crash.next_steps_addons": "Próbáld letiltani őket és frissíteni az oldalt. Ha ez nem segít, egy másik böngészőn vagy appon keresztül még mindig használhatod a Mastodont.",
@ -278,13 +278,13 @@
"firehose.remote": "Egyéb kiszolgálók",
"follow_request.authorize": "Hitelesítés",
"follow_request.reject": "Elutasítás",
"follow_requests.unlocked_explanation": "Bár a fiókod nincs zárolva, a(z) {domain} csapata úgy gondolta, hogy talán kézzel szeretnéd ellenőrizni a fiók követési kéréseit.",
"follow_requests.unlocked_explanation": "Bár a fiókod nincs zárolva, a(z) {domain} csapata úgy gondolta, hogy talán kézzel szeretnéd ellenőrizni ezen fiókok követési kéréseit.",
"followed_tags": "Követett hashtagek",
"footer.about": "Névjegy",
"footer.directory": "Profiltár",
"footer.get_app": "Alkalmazás beszerzése",
"footer.invite": "Emberek meghívása",
"footer.keyboard_shortcuts": "Billentyűparancsok",
"footer.keyboard_shortcuts": "Gyorsbillentyűk",
"footer.privacy_policy": "Adatvédelmi szabályzat",
"footer.source_code": "Forráskód megtekintése",
"footer.status": "Állapot",
@ -347,13 +347,13 @@
"keyboard_shortcuts.favourite": "Bejegyzés kedvencnek jelölése",
"keyboard_shortcuts.favourites": "Kedvencek lista megnyitása",
"keyboard_shortcuts.federated": "Föderációs idővonal megnyitása",
"keyboard_shortcuts.heading": "Billentyűparancsok",
"keyboard_shortcuts.heading": "Gyorsbillentyűk",
"keyboard_shortcuts.home": "Saját idővonal megnyitása",
"keyboard_shortcuts.hotkey": "Gyorsbillentyű",
"keyboard_shortcuts.legend": "jelmagyarázat megjelenítése",
"keyboard_shortcuts.local": "helyi idővonal megnyitása",
"keyboard_shortcuts.local": "Helyi idővonal megnyitása",
"keyboard_shortcuts.mention": "Szerző megemlítése",
"keyboard_shortcuts.muted": "némított felhasználók listájának megnyitása",
"keyboard_shortcuts.muted": "Némított felhasználók listájának megnyitása",
"keyboard_shortcuts.my_profile": "Saját profil megnyitása",
"keyboard_shortcuts.notifications": "Értesítések oszlop megnyitása",
"keyboard_shortcuts.open_media": "Média megnyitása",
@ -389,7 +389,7 @@
"lists.replies_policy.list": "A lista tagjai",
"lists.replies_policy.none": "Senki",
"lists.replies_policy.title": "Nekik mutassuk a válaszokat:",
"lists.search": "Keresés a követett személyek között",
"lists.search": "Keresés a követett emberek között",
"lists.subheading": "Saját listák",
"load_pending": "{count, plural, one {# új elem} other {# új elem}}",
"loading_indicator.label": "Betöltés…",
@ -399,7 +399,7 @@
"mute_modal.hide_notifications": "Rejtsük el a felhasználótól származó értesítéseket?",
"mute_modal.indefinite": "Határozatlan",
"navigation_bar.about": "Névjegy",
"navigation_bar.advanced_interface": "Haladó webes felület engedélyezése",
"navigation_bar.advanced_interface": "Megnyitás a speciális webes felületben",
"navigation_bar.blocks": "Letiltott felhasználók",
"navigation_bar.bookmarks": "Könyvjelzők",
"navigation_bar.community_timeline": "Helyi idővonal",
@ -411,9 +411,9 @@
"navigation_bar.explore": "Felfedezés",
"navigation_bar.favourites": "Kedvencek",
"navigation_bar.filters": "Némított szavak",
"navigation_bar.follow_requests": "Követési kérelmek",
"navigation_bar.follow_requests": "Követési kérések",
"navigation_bar.followed_tags": "Követett hashtagek",
"navigation_bar.follows_and_followers": "Követettek és követők",
"navigation_bar.follows_and_followers": "Követések és követők",
"navigation_bar.lists": "Listák",
"navigation_bar.logout": "Kijelentkezés",
"navigation_bar.mutes": "Némított felhasználók",
@ -449,7 +449,7 @@
"notifications.column_settings.follow_request": "Új követési kérelmek:",
"notifications.column_settings.mention": "Megemlítések:",
"notifications.column_settings.poll": "Szavazási eredmények:",
"notifications.column_settings.push": "Push értesítések",
"notifications.column_settings.push": "Leküldéses értesítések",
"notifications.column_settings.reblog": "Megtolások:",
"notifications.column_settings.show": "Megjelenítés az oszlopban",
"notifications.column_settings.sound": "Hang lejátszása",
@ -479,8 +479,8 @@
"onboarding.actions.go_to_home": "Ugrás a saját hírfolyamra",
"onboarding.compose.template": "Üdvözlet, #Mastodon!",
"onboarding.follows.empty": "Sajnos jelenleg nem jeleníthető meg eredmény. Kipróbálhatod a keresést vagy böngészheted a felfedező oldalon a követni kívánt személyeket, vagy próbáld meg később.",
"onboarding.follows.lead": "A saját hírfolyamod az elsődleges tapasztalás a Mastodonon. Minél több embert követsz, annál aktívabb és érdekesebb a dolog. Az induláshoz itt van néhány javaslat:",
"onboarding.follows.title": "Népszerű a Mastodonon",
"onboarding.follows.lead": "A kezdőlapod a Mastodon használatának elsődleges módja. Minél több embert követsz, annál aktívabbak és érdekesebbek lesznek a dolgok. Az induláshoz itt van néhány javaslat:",
"onboarding.follows.title": "Szabd személyre a kezdőlapodat",
"onboarding.profile.discoverable": "Saját profil beállítása felfedezhetőként",
"onboarding.profile.discoverable_hint": "A Mastodonon a felfedezhetőség választása esetén a saját bejegyzéseid megjelenhetnek a keresési eredmények és a felkapott tartalmak között, valamint a profilod a hozzád hasonló érdeklődési körrel rendelkező embereknél is ajánlásra kerülhet.",
"onboarding.profile.display_name": "Megjelenített név",
@ -499,14 +499,14 @@
"onboarding.start.lead": "Az új Mastodon-fiók használatra kész. Így hozhatod ki belőle a legtöbbet:",
"onboarding.start.skip": "Szeretnél előreugrani?",
"onboarding.start.title": "Ez sikerült!",
"onboarding.steps.follow_people.body": "Te állítod össze a saját hírfolyamodat. Töltsd meg érdekes emberekkel.",
"onboarding.steps.follow_people.body": "A Mastodon az érdekes emberek követéséről szól.",
"onboarding.steps.follow_people.title": "{count, plural, one {egy ember} other {# ember}} követése",
"onboarding.steps.publish_status.body": "Üdvözöljük a világot.",
"onboarding.steps.publish_status.title": "Az első bejegyzés létrehozása",
"onboarding.steps.setup_profile.body": "Mások nagyobb valószínűséggel lépnek kapcsolatba veled egy kitöltött profil esetén.",
"onboarding.steps.setup_profile.title": "Profilod testreszabása",
"onboarding.steps.share_profile.body": "Tudasd az ismerőseiddel, hogyan találhatnak meg a Mastodonon!",
"onboarding.steps.share_profile.title": "Profilod megosztása",
"onboarding.steps.share_profile.body": "Tudasd az ismerőseiddel, hogyan találhatnak meg a Mastodonon",
"onboarding.steps.share_profile.title": "Oszd meg a Mastodon profilodat",
"onboarding.tips.2fa": "<strong>Tudtad?</strong> A fiókod biztonságossá teheted, ha a fiók beállításaiban beállítod a kétlépcsős hitelesítést. Bármilyen választott TOTP alkalmazással működik, nincs szükség telefonszámra!",
"onboarding.tips.accounts_from_other_servers": "<strong>Tudtad?</strong> Mivel a Mastodon decentralizált, egyes profilok, amelyekkel találkozol, más kiszolgálókon lesznek tárolva. És mégis zökkenőmentesen kommunikálhatsz velük! A kiszolgáló a felhasználónevük második felében található!",
"onboarding.tips.migration": "<strong>Tudtad?</strong> Ha úgy érzed, hogy a {domain} már nem jó kiszolgáló a számodra, átköltözhetsz egy másik Mastodon kiszolgálóra anélkül, hogy elveszítenéd a követőidet. Akár saját kiszolgálót is üzemeltethetsz!",
@ -720,7 +720,7 @@
"upload_form.undo": "Törlés",
"upload_form.video_description": "Leírás siket, hallássérült, vak vagy gyengénlátó emberek számára",
"upload_modal.analyzing_picture": "Kép elemzése…",
"upload_modal.apply": "Alkalmazás",
"upload_modal.apply": "Alkalmaz",
"upload_modal.applying": "Alkalmazás…",
"upload_modal.choose_image": "Kép kiválasztása",
"upload_modal.description_placeholder": "A gyors, barna róka átugrik a lusta kutya fölött",

View file

@ -40,7 +40,7 @@
"account.follows.empty": "Šis (-i) naudotojas (-a) dar nieko neseka.",
"account.follows_you": "Seka tave",
"account.go_to_profile": "Eiti į profilį",
"account.hide_reblogs": "Slėpti \"boosts\" iš @{name}",
"account.hide_reblogs": "Slėpti pakėlimus iš @{name}",
"account.in_memoriam": "Atminimui.",
"account.joined_short": "Prisijungė",
"account.languages": "Keisti prenumeruojamas kalbas",
@ -49,19 +49,19 @@
"account.media": "Medija",
"account.mention": "Paminėti @{name}",
"account.moved_to": "{name} nurodė, kad dabar jų nauja paskyra yra:",
"account.mute": "tildyti @{name}",
"account.mute": "Nutildyti @{name}",
"account.mute_notifications_short": "Nutildyti pranešimus",
"account.mute_short": "Nutildyti",
"account.muted": "tildytas",
"account.muted": "Nutildytas",
"account.no_bio": "Nėra pateikto aprašymo.",
"account.open_original_page": "Atidaryti originalinį tinklalapį",
"account.open_original_page": "Atidaryti originalinį puslapį",
"account.posts": "Įrašai",
"account.posts_with_replies": "Įrašai ir atsakymai",
"account.report": "Pranešti @{name}",
"account.requested": "Laukiama patvirtinimo. Spausk, kad atšaukti sekimo užklausą.",
"account.requested": "Laukiama patvirtinimo. Spausk, kad atšaukti sekimo užklausą",
"account.requested_follow": "{name} paprašė tave sekti",
"account.share": "Bendrinti @{name} profilį",
"account.show_reblogs": "Rodyti \"boosts\" iš @{name}",
"account.show_reblogs": "Rodyti pakėlimus iš @{name}",
"account.statuses_counter": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}",
"account.unblock": "Atblokuoti @{name}",
"account.unblock_domain": "Atblokuoti domeną {domain}",
@ -73,7 +73,7 @@
"account.unmute_short": "Atitildyti",
"account_note.placeholder": "Spausk norėdamas (-a) pridėti pastabą",
"admin.dashboard.daily_retention": "Vartotojų išbuvimo rodiklis pagal dieną po registracijos",
"admin.dashboard.monthly_retention": "Vartotojų išbuvimo rodiklis pagal mėnesį po registracijos",
"admin.dashboard.monthly_retention": "Naudotojų išlaikymo rodiklis pagal mėnesį po registracijos",
"admin.dashboard.retention.average": "Vidurkis",
"admin.dashboard.retention.cohort": "Registravimo mėnuo",
"admin.dashboard.retention.cohort_size": "Nauji naudotojai",
@ -117,9 +117,9 @@
"column.favourites": "Mėgstamiausi",
"column.firehose": "Tiesioginiai padavimai",
"column.follow_requests": "Sekti prašymus",
"column.home": "Pradžia",
"column.home": "Pagrindinis",
"column.lists": "Sąrašai",
"column.mutes": "tildyti naudotojai",
"column.mutes": "Nutildyti naudotojai",
"column.notifications": "Pranešimai",
"column.pins": "Prisegti įrašai",
"column.public": "Federacinė laiko skalė",
@ -141,13 +141,13 @@
"compose.saved.body": "Įrašas išsaugotas.",
"compose_form.direct_message_warning_learn_more": "Sužinoti daugiau",
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.lock_disclaimer": "Jūsų paskyra nėra {locked}. Kiekvienas gali jus sekti ir peržiūrėti tik sekėjams skirtus įrašus.",
"compose_form.hashtag_warning": "Šis įrašas nebus įtraukta į jokį saitažodį, nes ji nėra vieša. Tik viešų įrašų galima ieškoti pagal saitažodį.",
"compose_form.lock_disclaimer": "Tavo paskyra nėra {locked}. Bet kas gali sekti tave ir peržiūrėti tik sekėjams skirtus įrašus.",
"compose_form.lock_disclaimer.lock": "užrakinta",
"compose_form.placeholder": "Kas tavo mintyse?",
"compose_form.poll.add_option": "Pridėti pasirinkimą",
"compose_form.poll.duration": "Apklausos trukmė",
"compose_form.poll.option_placeholder": "Pasirinkimas {number}",
"compose_form.poll.option_placeholder": "{number} pasirinkimas",
"compose_form.poll.remove_option": "Pašalinti šį pasirinkimą",
"compose_form.poll.switch_to_multiple": "Keisti apklausą, kad būtų galima pasirinkti kelis pasirinkimus",
"compose_form.poll.switch_to_single": "Pakeisti apklausą, kad būtų galima pasirinkti vieną variantą",
@ -528,6 +528,8 @@
"search_results.hashtags": "Saitažodžiai",
"search_results.nothing_found": "Nepavyko rasti nieko pagal šiuos paieškos terminus.",
"search_results.statuses": "Toots",
"server_banner.about_active_users": "Žmonės, kurie naudojosi šiuo serveriu per pastarąsias 30 dienų (mėnesio aktyvūs naudotojai)",
"server_banner.active_users": "aktyvūs naudotojai",
"sign_in_banner.sign_in": "Prisijungimas",
"sign_in_banner.text": "Prisijunk, kad galėtum sekti profilius arba saitažodžius, mėgsti, bendrinti ir atsakyti į įrašus. Taip pat gali bendrauti iš savo paskyros kitame serveryje.",
"status.admin_status": "Open this status in the moderation interface",

View file

@ -21,6 +21,7 @@
"account.blocked": "ဘလော့ထားသည်",
"account.browse_more_on_origin_server": "မူရင်းပရိုဖိုင်တွင် ပိုမိုကြည့်ရှုပါ။",
"account.cancel_follow_request": "စောင့်ကြည့်မှု ပယ်ဖျက်ခြင်း",
"account.copy": "လင့်ခ်ကို ပရိုဖိုင်သို့ ကူးယူပါ",
"account.direct": "@{name} သီးသန့် သိရှိနိုင်အောင် မန်းရှင်းခေါ်မည်",
"account.disable_notifications": "@{name} ပို့စ်တင်သည့်အခါ ကျွန်ုပ်ထံ အသိပေးခြင်း မပြုလုပ်ရန်။",
"account.domain_blocked": "ဒိုမိန်း ပိတ်ပင်ထားခဲ့သည်",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "ဖတ်ပြီးသားအဖြစ်မှတ်ထားပါ",
"conversation.open": "Conversation ကိုကြည့်မည်",
"conversation.with": "{အမည်များ} ဖြင့်",
"copy_icon_button.copied": "ကလစ်ဘုတ်သို့ ကူးပါ",
"copypaste.copied": "ကူယူပြီးပါပြီ",
"copypaste.copy_to_clipboard": "ကလစ်ဘုတ်သို့ ကူးပါ",
"directory.federated": "သင် သိသော ဖက်ဒီမှ",
@ -389,6 +391,7 @@
"lists.search": "မိမိဖောလိုးထားသူများမှရှာဖွေမည်",
"lists.subheading": "သင့်၏စာရင်းများ",
"load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "လုပ်ဆောင်နေသည်…",
"media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
"moved_to_account_banner.text": "{movedToAccount} အကောင့်သို့ပြောင်းလဲထားသဖြင့် {disabledAccount} အကောင့်မှာပိတ်ထားသည်",
"mute_modal.duration": "ကြာချိန်",
@ -477,6 +480,13 @@
"onboarding.follows.empty": "ယခုအချိန် မည်သည့်ရလဒ်ကိုမျှ မပြသနိုင်ပါ။ လူများကိုစောင့်ကြည့်ရန်အတွက် Explore စာမျက်နှာကို အသုံးပြု၍ စမ်းကြည့်နိုင်သည် သို့မဟုတ် နောက်မှ ထပ်စမ်းကြည့်ပါ။",
"onboarding.follows.lead": "သင့်ကိုယ်ပိုင်ပို့စ်များ တင်နိုင်သည်။ သင်စောင့်ကြည့်သူ များလေလေ၊ စိတ်ဝင်စားစရာကောင်းသောပို့စ်များ တွေ့ရလေဖြစ်သည်။ ဤပရိုဖိုင်များမှာ ကောင်းမွန်သောအစပြုမှုတစ်ခုဖြစ်ပြီး ၎င်းတို့ကိုစောင့်ကြည့်ခြင်းမှလည်း အချိန်မရွေး ပယ်ဖျက်နိုင်ပါသည်။",
"onboarding.follows.title": "Mastodon တွင် ရေပန်းစားခြင်း",
"onboarding.profile.discoverable": "ပရိုဖိုင် ရှာဖွေနိုင်ပါမည်",
"onboarding.profile.display_name": "ဖော်ပြမည့်အမည်",
"onboarding.profile.display_name_hint": "သင့်အမည်အပြည့်အစုံ သို့မဟုတ် သင့်အမည်ပြောင်။",
"onboarding.profile.note": "ကိုယ်ရေးအကျဉ်း",
"onboarding.profile.save_and_continue": "သိမ်းပြီး ဆက်လုပ်ပါ",
"onboarding.profile.title": "ပရိုဖိုင်စနစ် ထည့်သွင်းခြင်း",
"onboarding.profile.upload_avatar": "ပရိုဖိုင်ပုံ အပ်လုဒ်လုပ်ပါ",
"onboarding.share.lead": "Mastodon တွင် သင့်အား မည်သို့ရှာတွေ့နိုင်သည်ကို အသိပေးပါ။",
"onboarding.share.message": "Mastodon ရှိ ကျွန်ုပ်၏အမည်မှာ {username} ဖြစ်သည်။ ကျွန်ုပ်ကို {url} တွင် စောင့်ကြည့်နိုင်ပါသည်",
"onboarding.share.next_steps": "ဖြစ်နိုင်ချေရှိသော နောက်အဆင့်များ -",
@ -520,6 +530,7 @@
"privacy.unlisted.short": "စာရင်းမသွင်းထားပါ",
"privacy_policy.last_updated": "နောက်ဆုံး ပြင်ဆင်ခဲ့သည့်ရက်စွဲ {date}",
"privacy_policy.title": "ကိုယ်ရေးအချက်အလက်မူဝါဒ",
"recommended": "အကြံပြုသည်",
"refresh": "ပြန်လည်စတင်ပါ",
"regeneration_indicator.label": "လုပ်ဆောင်နေသည်…",
"regeneration_indicator.sublabel": "သင့်ပင်မစာမျက်နှာကို ပြင်ဆင်နေပါသည်။",
@ -590,6 +601,7 @@
"search.quick_action.status_search": "{x} နှင့် ကိုက်ညီသော ပို့စ်များ",
"search.search_or_paste": "URL ရိုက်ထည့်ပါ သို့မဟုတ် ရှာဖွေပါ",
"search_popout.full_text_search_disabled_message": "{domain} တွင် မရနိုင်ပါ။",
"search_popout.full_text_search_logged_out_message": "အကောင့်ဝင်ထားမှသာ ရနိုင်သည်။",
"search_popout.language_code": "ISO ဘာသာစကားကုဒ်",
"search_popout.options": "ရွေးချယ်ထားသည်များ ရှာဖွေရန်",
"search_popout.quick_actions": "အမြန်လုပ်ဆောင်မှုများ",

View file

@ -7,7 +7,7 @@
"about.domain_blocks.silenced.explanation": "Normalmente não verá perfis e conteúdo deste servidor, a menos que os procure explicitamente ou opte por os seguir.",
"about.domain_blocks.silenced.title": "Limitados",
"about.domain_blocks.suspended.explanation": "Nenhum dado deste servidor será processado, armazenado ou trocado, impossibilitando qualquer interação ou comunicação com os utilizadores dessas instâncias.",
"about.domain_blocks.suspended.title": "Supensos",
"about.domain_blocks.suspended.title": "Suspensos",
"about.not_available": "Esta informação não foi disponibilizada neste servidor.",
"about.powered_by": "Rede social descentralizada baseada no {mastodon}",
"about.rules": "Regras do servidor",

View file

@ -4,7 +4,8 @@ class AttachmentBatch
# Maximum amount of objects you can delete in an S3 API call. It's
# important to remember that this does not correspond to the number
# of records in the batch, since records can have multiple attachments
LIMIT = 1_000
LIMIT = ENV.fetch('S3_BATCH_DELETE_LIMIT', 1000).to_i
MAX_RETRY = ENV.fetch('S3_BATCH_DELETE_RETRY', 3).to_i
# Attributes generated and maintained by Paperclip (not all of them
# are always used on every class, however)
@ -95,6 +96,7 @@ class AttachmentBatch
# objects can be processed at once, so we have to potentially
# separate them into multiple calls.
retries = 0
keys.each_slice(LIMIT) do |keys_slice|
logger.debug { "Deleting #{keys_slice.size} objects" }
@ -102,6 +104,17 @@ class AttachmentBatch
objects: keys_slice.map { |key| { key: key } },
quiet: true,
})
rescue => e
retries += 1
if retries < MAX_RETRY
logger.debug "Retry #{retries}/#{MAX_RETRY} after #{e.message}"
sleep 2**retries
retry
else
logger.error "Batch deletion from S3 failed after #{e.message}"
raise e
end
end
end

View file

@ -37,6 +37,7 @@ class LinkDetailsExtractor
def language
lang = json['inLanguage']
lang = lang.first if lang.is_a?(Array)
lang.is_a?(Hash) ? (lang['alternateName'] || lang['name']) : lang
end

View file

@ -9,9 +9,7 @@
# url :string
#
class PreviewCardsStatus < ApplicationRecord
# Composite primary keys are not properly supported in Rails. However,
# we shouldn't need this anyway...
self.primary_key = nil
self.primary_key = [:preview_card_id, :status_id]
belongs_to :preview_card
belongs_to :status

View file

@ -108,8 +108,7 @@ class Status < ApplicationRecord
has_and_belongs_to_many :tags
# Because of a composite primary key, the `dependent` option cannot be used on this association
has_one :preview_cards_status, inverse_of: :status # rubocop:disable Rails/HasManyOrHasOneDependent
has_one :preview_cards_status, inverse_of: :status, dependent: :delete
has_one :notification, as: :activity, dependent: :destroy
has_one :status_stat, inverse_of: :status, dependent: nil
@ -178,7 +177,6 @@ class Status < ApplicationRecord
# The `prepend: true` option below ensures this runs before
# the `dependent: destroy` callbacks remove relevant records
before_destroy :unlink_from_conversations!, prepend: true
before_destroy :reset_preview_card!
cache_associated :application,
:media_attachments,

View file

@ -14,7 +14,6 @@ require 'active_job/railtie'
# require 'action_mailbox/engine'
# require 'action_text/engine'
# require 'rails/test_unit/railtie'
require 'sprockets/railtie'
# Used to be implicitly required in action_mailbox/engine
require 'mail'

View file

@ -71,17 +71,6 @@ Rails.application.configure do
# Highlight code that enqueued background job in logs.
config.active_job.verbose_enqueue_logs = true
# Debug mode disables concatenation and preprocessing of assets.
config.assets.debug = true
# Suppress logger output for asset requests.
config.assets.quiet = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true

View file

@ -1,16 +0,0 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
Rails.application.config.assets.initialize_on_precompile = true

View file

@ -20,7 +20,7 @@ hu:
attributes:
username:
invalid: csak betűket, számokat vagy alávonást tartalmazhat
reserved: fenntartott
reserved: foglalt
admin/webhook:
attributes:
url:

View file

@ -44,7 +44,7 @@ hu:
action: Jelszó módosítása
explanation: A fiókodhoz tartozó jelszó módosítását kezdeményezted.
extra: Amennyiben nem te kezdeményezted a módosítást, kérjük tekintsd ezt az emailt tárgytalannak. A jelszavad változatlan marad mindaddig, amíg újat nem hozol létre a fenti linkre kattintva.
subject: 'Mastodon: Jelszó visszaállítási lépések'
subject: 'Mastodon: Jelszóvisszaállítási utasítások'
title: Jelszó visszaállítása
two_factor_disabled:
explanation: A fiókod kétlépcsős hitelesítését kikapcsoltuk. A bejelentkezés mostantól csak az e-mail cím és a jelszó használatával lesz lehetséges.
@ -52,14 +52,14 @@ hu:
title: Kétlépcsős hitelesítés kikapcsolva
two_factor_enabled:
explanation: A kétlépcsős hitelesítést engedélyeztük a fiókodban. A bejelentkezéshez a párosított TOTP alkalmazás által generált tokenre lesz szükség.
subject: Kétlépcsős azonosítás engedélyezve
subject: 'Mastodon: Kétlépcsős azonosítás engedélyezve'
title: Kétlépcsős hitelesítés engedélyezve
two_factor_recovery_codes_changed:
explanation: A korábbi helyreállítási kódok letiltásra és újragenerálásra kerültek.
subject: Kétlépcsős helyreállítási kódok újra létrejöttek
subject: 'Mastodon: Kétlépcsős helyreállítási kódok újból előállítva'
title: A kétlépcsős kódok megváltoztak
unlock_instructions:
subject: 'Mastodon: Feloldási lépések'
subject: 'Mastodon: Feloldási utasítások'
webauthn_credential:
added:
explanation: A következő biztonsági kulcsot hozzáadtuk a fiókodhoz

View file

@ -4,7 +4,7 @@ hu:
about_mastodon_html: 'A jövő közösségi hálózata: Hirdetések és céges megfigyelés nélkül, etikus dizájnnal és decentralizációval! Legyél a saját adataid ura a Mastodonnal!'
contact_missing: Nincs megadva
contact_unavailable: N/A
hosted_on: "%{domain} Mastodon szerver"
hosted_on: "%{domain} Mastodon-kiszolgáló"
title: Névjegy
accounts:
follow: Követés
@ -747,7 +747,7 @@ hu:
desc_html: Ez hCaptcha-ból származó külső scripteket használ, mely biztonsági vagy adatvédelmi résnek bizonyulhat. Ezen kívül ez <strong>a regisztrációs folyamatot jelentősen megnehezítheti bizonyos (kifejezetten különleges szükségletű) emberek számára</strong>. Emiatt fontold meg más módszerek, mint pl. jóváhagyás-alapú vagy meghívásalapú regisztráció használatát.
title: Az új felhasználóknak egy CAPTCHA-t kell megoldaniuk, hogy megerősítsék a fiókjuk regisztrációját
content_retention:
preamble: Felhasználók által generált tartalom Mastodonon való tárolásának szabályozása.
preamble: A felhasználók által előállított tartalom Mastodonon való tárolásának szabályozása.
title: Tartalom megtartása
default_noindex:
desc_html: Azokat a felhasználókat érinti, akik nem módosították ezt a beállítást
@ -1007,8 +1007,8 @@ hu:
hint_html: Ha másik fiókról kívánsz átlépni erre a fiókra, itt létrehozhatsz egy aliast, amelyre szükség van, mielőtt folytathatod a követők áthelyezését a régi fiókból erre. Ez az áthelyezés önmagában <strong>ártalmatlan és visszafordítható</strong> folyamat. <strong>A fiók áttelepítése a régi fiókból indul el. </strong>
remove: Alias szétkapcsolása
appearance:
advanced_web_interface: Haladó webes felület
advanced_web_interface_hint: 'Ha szeretnéd, a teljes képernyőszélességet felhasználhatod. A haladó webes felülettel különböző oszlopokat állíthatsz be, hogy egyszerre annyi infót láthass, amennyit csak akarsz: Saját idővonal, értesítések, föderációs idővonal, bármennyi lista vagy hashtag.'
advanced_web_interface: Speciális webes felület
advanced_web_interface_hint: 'Ha szeretnéd, a képernyő teljes szélességét kihasználhatod. A speciális webes felülettel különböző oszlopokat állíthatsz be, hogy egyszerre annyi információt láthass, amennyit csak akarsz: Kezdőoldal, értesítések, föderációs idővonal, bármennyi lista vagy hashtag.'
animations_and_accessibility: Animáció és akadálymentesítés
confirmation_dialogs: Megerősítő párbeszédablakok
discovery: Felfedezés
@ -1052,7 +1052,7 @@ hu:
delete_account: Felhasználói fiók törlése
delete_account_html: Felhasználói fiókod törléséhez <a href="%{path}">kattints ide</a>. A rendszer újbóli megerősítést fog kérni.
description:
prefix_invited_by_user: "@%{name} meghív téged, hogy csatlakozz ehhez a Mastodon kiszolgálóhoz."
prefix_invited_by_user: "@%{name} meghív téged, hogy csatlakozz ehhez a Mastodon-kiszolgálóhoz."
prefix_sign_up: Regisztrláj még ma a Mastodonra!
suffix: Egy fiókkal követhetsz másokat, bejegyzéseket tehetsz közzé, eszmét cserélhetsz más Mastodon szerverek felhasználóival!
didnt_get_confirmation: Nem kaptál visszaigazoló hivatkozást?
@ -1101,7 +1101,7 @@ hu:
title: 'Bejelentkezés ide: %{domain}'
sign_up:
manual_review: A(z) %{domain} regisztrációi a moderátorok kézi felülvizsgálatán mennek át. Hogy segítsd a regisztráció feldolgozását, írj röviden magadról, és hogy miért szeretnél fiókot a(z) %{domain} oldalon.
preamble: Egy fiókkal ezen a Mastodon kiszolgálón követhetsz bárkit a hálózaton, függetlenül attól, hogy az illető fiókja melyik kiszolgálón található.
preamble: Egy fiókkal ezen a Mastodon-kiszolgálón követhetsz bárkit a hálózaton, függetlenül attól, hogy az illető fiókja melyik kiszolgálón található.
title: Állítsuk be a fiókod a %{domain} kiszolgálón.
status:
account_status: Fiók állapota
@ -1234,7 +1234,7 @@ hu:
filters:
contexts:
account: Profil
home: Saját idővonal
home: Kezdőlap és listák
notifications: Értesítések
public: Nyilvános idővonalak
thread: Beszélgetések
@ -1245,7 +1245,7 @@ hu:
statuses_hint_html: Ez a szűrő egyedi bejegyzések kiválasztására vonatkozik, függetlenül attól, hogy megfelelnek-e a lenti kulcsszavaknak. <a href="%{path}">Engedélyezze vagy távolítsa el a bejegyzéseket a szűrőből</a>.
title: Szűrő szerkesztése
errors:
deprecated_api_multiple_keywords: Ezek a paraméterek nem módosíthatóak az alkalmazásból, mert több mint egy szűrőkulcsszóra is hatással vannak. Használd az alkalmazás vagy a webes felület újabb verzióját.
deprecated_api_multiple_keywords: Ezek a paraméterek nem módosíthatók az alkalmazásból, mert egynél több szűrőkulcsszóra is hatással vannak. Használd az alkalmazás vagy a webes felület újabb verzióját.
invalid_context: A megadott kontextus hamis vagy hiányzik
index:
contexts: 'Szűrés helye: %{contexts}'
@ -1396,7 +1396,7 @@ hu:
unsubscribe:
action: Igen, leiratkozás
complete: Leiratkozva
confirmation_html: Biztos vagy benne, hogy le szeretnél iratkozni arról, hogy %{type} típusú üzeneteket kapj a %{domain} Mastodon kiszolgálón a %{email} címedre? Bármikor újra feliratkozhatsz az <a href="%{settings_path}">email értesítések beállításainál</a>.
confirmation_html: 'Biztos, hogy leiratkozol arról, hogy %{type} típusú üzeneteket kapj a %{domain} Mastodon-kiszolgálótól erre a címedre: %{email}? Bármikor újra feliratkozhatsz az <a href="%{settings_path}">e-mail-értesítések beállításánál</a>.'
emails:
notification_emails:
favourite: kedvencnek jelölésről email értesítő
@ -1405,7 +1405,7 @@ hu:
mention: megemlítésről email értesítő
reblog: megtolásról email értesítő
resubscribe_html: Ha tévedésből iratkoztál le, újra feliratkozhatsz az <a href="%{settings_path}">email értesítések beállításainál</a>.
success_html: Mostantól nem kapsz %{type} típusú üzeneket a %{domain} Mastodon kiszolgálón a %{email} címedre.
success_html: 'Mostantól nem kapsz %{type} típusú üzeneket a(z) %{domain} Mastodon-kiszolgálón erre a címedre: %{email}.'
title: Leiratkozás
media_attachments:
validations:
@ -1743,9 +1743,9 @@ hu:
tags:
does_not_match_previous_name: nem illeszkedik az előző névvel
themes:
contrast: Mastodon (Nagy kontrasztú)
default: Mastodon (Sötét)
mastodon-light: Mastodon (Világos)
contrast: Mastodon (nagy kontrasztú)
default: Mastodon (sötét)
mastodon-light: Mastodon (világos)
time:
formats:
default: "%Y. %b %d., %H:%M"
@ -1782,7 +1782,7 @@ hu:
subject: A %{date}-i fellebbezésedet visszautasították
title: Fellebbezés visszautasítva
backup_ready:
explanation: A Mastodon fiókod teljes mentését kérted. A mentés kész ás letölthető!
explanation: A Mastodon-fiókod teljes mentését kérted. A mentés elkészült, és letölthető.
subject: Az adataidról készült archív letöltésre kész
title: Archiválás
suspicious_sign_in:

View file

@ -1324,6 +1324,7 @@ my:
'86400': ရက်
expires_in_prompt: ဘယ်တော့မှ
generate: ဖိတ်ကြားချက်လင့်ခ် ဖန်တီးပါ
invalid: ဤဖိတ်ကြားချက်မှာ မမှန်ကန်ပါ
invited_by: သင့်ကို ဖိတ်ခေါ်ထားသည် -
max_uses:
other: "%{count} အသုံးပြုမှုများ"

View file

@ -81,8 +81,8 @@ hu:
bootstrap_timeline_accounts: Ezek a fiókok ki lesznek tűzve az új felhasználók követési javaslatainak élére.
closed_registrations_message: Akkor jelenik meg, amikor a regisztráció le van zárva
content_cache_retention_period: A más kiszolgálókról származó bejegyzések megadott számú nap után törölve lesznek, ha pozitív értékre van állítva. Ez lehet, hogy nem fordítható vissza.
custom_css: A Mastodon webes verziójában használhatsz egyedi stílusokat.
mascot: Felülvágja a haladó webes felületen található illusztrációt.
custom_css: A Mastodon webes verziójában használhatsz egyéni stílusokat.
mascot: Felülbírálja a speciális webes felületen található illusztrációt.
media_cache_retention_period: A letöltött médiafájlok megadott számú nap után törölve lesznek, ha pozitív értékre van állítva, és igény szerint újból le lesznek töltve.
peers_api_enabled: Azon domainek listája, melyekkel ez a kiszolgáló találkozott a fediverzumban. Nem csatolunk adatot arról, hogy föderált kapcsolatban vagy-e az adott kiszolgálóval, csak arról, hogy a kiszolgálód tud a másikról. Ezt olyan szolgáltatások használják, melyek általában a föderációról készítenek statisztikákat.
profile_directory: A profilok jegyzéke minden olyan felhasználót felsorol, akik engedélyezték a felfedezhetőségüket.
@ -103,7 +103,7 @@ hu:
form_challenge:
current_password: Beléptél egy biztonsági térben
imports:
data: Egy másik Mastodon kiszolgálóról exportált CSV-fájl
data: Egy másik Mastodon-kiszolgálóról exportált CSV-fájl
invite_request:
text: Ez segít nekünk átnézni a jelentkezésedet
ip_block:
@ -199,7 +199,7 @@ hu:
otp_attempt: Kétlépcsős azonosító kód
password: Jelszó
phrase: Kulcsszó vagy kifejezés
setting_advanced_layout: Haladó webes felület engedélyezése
setting_advanced_layout: Speciális webes felület engedélyezése
setting_aggregate_reblogs: Megtolások csoportosítása az idővonalakon
setting_always_send_emails: E-mail értesítések küldése mindig
setting_auto_play_gif: GIF-ek automatikus lejátszása

View file

@ -43,7 +43,7 @@ hy:
setting_display_media_hide_all: Երբեք մեդիա ցոյց չտալ
setting_display_media_show_all: Մեդիա միշտ ցոյց տալ
setting_use_blurhash: Կտորները հիմնուում են թաքցուած վիզուալի վրայ՝ խամրեցնելով դետալները
setting_use_pending_items: Թաքցնել հոսքի թարմացումները կտտոի ետեւում՝ աւտօմատ թարմացուող հոսքի փոխարէն
setting_use_pending_items: Թաքցնել հոսքի թարմացումները կոճակի ետեւում՝ աւտօմատ թարմացուող հոսքի փոխարէն
username: Միայն լատինատառեր, թուեր եւ տակի գծիկ
whole_word: Եթէ բանալի բառը կամ արտայայտութիւնը պարունակում է միայն այբբենական նիշեր եւ թուեր, ապա այն կիրառուելու է ամբողջ բառի հետ համընկնելու դէպքում միայն
domain_allow:

View file

@ -63,6 +63,8 @@ lt:
setting_use_pending_items: Slėpti laiko skalės naujienas po paspaudimo, vietoj automatinio kanalo slinkimo
username: Gali naudoti raides, skaičius ir pabraukimus
whole_word: Kai raktažodis ar frazė yra tik raidinis ir skaitmeninis, jis bus taikomas tik tada, jei atitiks visą žodį
email_domain_block:
with_dns_records: Bus bandoma išspręsti nurodyto domeno DNS įrašus, o rezultatai taip pat bus blokuojami
featured_tag:
name: 'Štai keletas pastaruoju metu dažniausiai saitažodžių, kurių tu naudojai:'
filters:
@ -77,15 +79,98 @@ lt:
site_contact_email: Kaip žmonės gali su tavimi susisiekti teisiniais ar pagalbos užklausimais.
site_contact_username: Kaip žmonės gali tave pasiekti Mastodon.
site_extended_description: Bet kokia papildoma informacija, kuri gali būti naudinga lankytojams ir naudotojams. Gali būti struktūrizuota naudojant Markdown sintaksę.
thumbnail: Maždaug 2:1 dydžio vaizdas, rodomas šalia tavo serverio informacijos.
timeline_preview: Atsijungę lankytojai galės naršyti naujausius viešus įrašus, esančius serveryje.
trends: Trendai rodo, kurios įrašai, saitažodžiai ir naujienų istorijos tavo serveryje sulaukia didžiausio susidomėjimo.
sessions:
otp: 'Įvesk telefono programėlėje sugeneruotą dviejų tapatybės kodą arba naudok vieną iš atkūrimo kodų:'
webauthn: Jei tai USB raktas, būtinai jį įkišk ir, jei reikia, paspausk.
settings:
indexable: Tavo profilio puslapis gali būti rodomas paieškos rezultatuose Google, Bing ir kituose.
user:
chosen_languages: Kai pažymėta, viešose laiko skalėse bus rodomi tik įrašai pasirinktomis kalbomis
role: Vaidmuo valdo, kokius leidimus naudotojas (-a) turi
labels:
account:
indexable: Įtraukti viešus įrašus į paieškos rezultatus
show_collections: Rodyti sekimus ir sekėjus profilyje
unlocked: Automatiškai priimti naujus sekėjus
account_warning_preset:
title: Pavadinimas
admin_account_action:
include_statuses: Įtraukti praneštus įrašus į el. laišką
defaults:
avatar: Profilio nuotrauka
bot: Tai automatinė paskyra
chosen_languages: Filtruoti kalbas
display_name: Rodomas vardas
email: El. pašto adresas
expires_in: Nustoja galioti po
fields: Papildomi laukai
irreversible: Mesti vietoj slėpti
locale: Sąsajos kalba
max_uses: Maksimalus naudojimo skaičius
new_password: Naujas slaptažodis
note: Biografija
password: Slaptažodis
phrase: Raktažodis arba frazė
setting_auto_play_gif: Automatiškai leisti animuotų GIF
setting_boost_modal: Rodyti patvirtinimo dialogą prieš pakėliant įrašą
setting_default_language: Skelbimo kalba
setting_default_privacy: Skelbimo privatumas
setting_default_sensitive: Visada žymėti mediją kaip jautrią
setting_delete_modal: Rodyti patvirtinimo dialogą prieš ištrinant įrašą
setting_display_media: Medijos rodymas
setting_display_media_hide_all: Slėpti viską
setting_display_media_show_all: Rodyti viską
setting_expand_spoilers: Visada išplėsti įrašus, pažymėtus turinio įspėjimais
setting_hide_network: Slėpti savo socialinę diagramą
setting_system_font_ui: Naudoti numatytąjį sistemos šriftą
setting_theme: Svetainės tema
setting_use_pending_items: Lėtas režimas
title: Pavadinimas
type: Importo tipas
username: Naudotojo vardas
username_or_email: Naudotojo vardas arba el. paštas
whole_word: Visas žodis
email_domain_block:
with_dns_records: Įtraukti MX įrašus ir domeno IP adresus
featured_tag:
name: Saitažodis
filters:
actions:
hide: Slėpti visiškai
warn: Slėpti su įspėjimu
form_admin_settings:
activity_api_enabled: Skelbti suvestinį statistiką apie naudotojų veiklą per API
bootstrap_timeline_accounts: Visada rekomenduoti šias paskyras naujiems naudotojams
content_cache_retention_period: Turinio talpyklos išlaikymo laikotarpis
custom_css: Pasirinktinis CSS
mascot: Pasirinktinis talismanas (pasenęs)
registrations_mode: Kas gali užsiregistruoti
show_domain_blocks_rationale: Rodyti, kodėl domenai buvo užblokuoti
site_extended_description: Išplėstas aprašymas
site_short_description: Serverio aprašymas
site_terms: Privatumo politika
site_title: Serverio pavadinimas
theme: Numatytoji tema
thumbnail: Serverio miniatūra
invite_request:
text: Kodėl nori prisijungti?
notification_emails:
favourite: Kažkas pamėgo tavo įrašą
follow: Kažkas seka tave
follow_request: Kažkas paprašė sekti tave
mention: Kažkas paminėjo tave
pending_account: Reikia peržiūros naujam paskyrui
reblog: Kažkas pakėlė tavo įrašą
software_updates:
label: Yra nauja Mastodon versija
patch: Pranešti apie klaidų ištaisymo atnaujinimus
rule:
text: Taisyklė
settings:
show_application: Rodyti, iš kurios programėles išsiuntei įrašą
tag:
listable: Leisti šį saitažodį rodyti paieškose ir pasiūlymuose
name: Saitažodis
@ -93,11 +178,15 @@ lt:
usable: Leisti įrašams naudoti šį saitažodį
user:
role: Vaidmuo
time_zone: Laiko juosta
user_role:
color: Ženklelio spalva
highlighted: Rodyti vaidmenį kaip ženklelį naudotojo profiliuose
name: Pavadinimas
permissions_as_keys: Leidimai
position: Prioritetas
webhook:
events: Įgalinti įvykiai
events: Įjungti įvykiai
template: Naudingosios apkrovos šablonas
url: Galutinio taško URL
'no': Ne

View file

@ -472,15 +472,13 @@ module Mastodon::CLI
end
total = 0
total += Account.where(id: ::Follow.where(account: account).select(:target_account_id)).count if options[:follows]
total += Account.where(id: ::Follow.where(target_account: account).select(:account_id)).count if options[:followers]
total += account.following.reorder(nil).count if options[:follows]
total += account.followers.reorder(nil).count if options[:followers]
progress = create_progress_bar(total)
processed = 0
if options[:follows]
scope = Account.where(id: ::Follow.where(account: account).select(:target_account_id))
scope.find_each do |target_account|
account.following.reorder(nil).find_each do |target_account|
UnfollowService.new.call(account, target_account)
rescue => e
progress.log pastel.red("Error processing #{target_account.id}: #{e}")
@ -493,9 +491,7 @@ module Mastodon::CLI
end
if options[:followers]
scope = Account.where(id: ::Follow.where(target_account: account).select(:account_id))
scope.find_each do |target_account|
account.followers.reorder(nil).find_each do |target_account|
UnfollowService.new.call(target_account, account)
rescue => e
progress.log pastel.red("Error processing #{target_account.id}: #{e}")

View file

@ -97,6 +97,8 @@ module Mastodon::CLI
say("Removed #{custom_emojis_count} custom emojis#{dry_run_mode_suffix}", :green)
end
CRAWL_SLEEP_TIME = 20
option :concurrency, type: :numeric, default: 50, aliases: [:c]
option :format, type: :string, default: 'summary', aliases: [:f]
option :exclude_suspended, type: :boolean, default: false, aliases: [:x]
@ -168,8 +170,8 @@ module Mastodon::CLI
pool.post(domain, &work_unit)
end
sleep 20
sleep 20 until pool.queue_length.zero?
sleep CRAWL_SLEEP_TIME
sleep CRAWL_SLEEP_TIME until pool.queue_length.zero?
pool.shutdown
pool.wait_for_termination(20)

View file

@ -346,7 +346,7 @@ module Mastodon::CLI
remove_index_if_exists!(:announcement_reactions, 'index_announcement_reactions_on_account_id_and_announcement_id')
say 'Removing duplicate account identity proofs…'
say 'Removing duplicate announcement reactions…'
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM announcement_reactions GROUP BY account_id, announcement_id, name HAVING count(*) > 1").each do |row|
AnnouncementReaction.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy)
end
@ -431,7 +431,7 @@ module Mastodon::CLI
def deduplicate_domain_blocks!
remove_index_if_exists!(:domain_blocks, 'index_domain_blocks_on_domain')
say 'Deduplicating domain_allows…'
say 'Deduplicating domain_blocks…'
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM domain_blocks GROUP BY domain HAVING count(*) > 1").each do |row|
domain_blocks = DomainBlock.where(id: row['ids'].split(',')).by_severity.reverse.to_a
@ -462,7 +462,7 @@ module Mastodon::CLI
UnavailableDomain.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy)
end
say 'Restoring domain_allows indexes…'
say 'Restoring unavailable_domains indexes…'
ActiveRecord::Base.connection.add_index :unavailable_domains, ['domain'], name: 'index_unavailable_domains_on_domain', unique: true
end

View file

@ -120,7 +120,7 @@ module Mastodon::CLI
say('Beginning removal of now-orphaned media attachments to free up disk space...')
scope = MediaAttachment.reorder(nil).unattached.where('created_at < ?', options[:days].pred.days.ago)
scope = MediaAttachment.unattached.where('created_at < ?', options[:days].pred.days.ago)
processed = 0
removed = 0
progress = create_progress_bar(scope.count)

View file

@ -198,7 +198,7 @@
"eslint-plugin-jsx-a11y": "~6.8.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "~6.1.1",
"eslint-plugin-react": "~7.33.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"jest": "^29.5.0",

BIN
spec/fixtures/files/elite-assets.tar.gz vendored Normal file

Binary file not shown.

View file

@ -12,7 +12,7 @@ describe PostDeploymentMigrationGenerator, type: :generator do
include FileUtils
tests described_class
destination File.expand_path('../../tmp', __dir__)
destination Rails.root.join('tmp', 'generator-test')
before { prepare_destination }
after { rm_rf(destination_root) }

View file

@ -29,15 +29,25 @@ describe ApplicationHelper do
describe 'body_classes' do
context 'with a body class string from a controller' do
before do
without_partial_double_verification do
allow(helper).to receive_messages(body_class_string: 'modal-layout compose-standalone', current_theme: 'default', current_account: Fabricate(:account))
end
end
before { helper.extend controller_helpers }
it 'uses the controller body classes in the result' do
expect(helper.body_classes).to match(/modal-layout compose-standalone/)
end
private
def controller_helpers
Module.new do
def body_class_string = 'modal-layout compose-standalone'
def current_account
@current_account ||= Fabricate(:account)
end
def current_theme = 'default'
end
end
end
end
@ -122,9 +132,7 @@ describe ApplicationHelper do
describe 'available_sign_up_path' do
context 'when registrations are closed' do
before do
without_partial_double_verification do
allow(Setting).to receive(:registrations_mode).and_return('none')
end
allow(Setting).to receive(:[]).with('registrations_mode').and_return 'none'
end
it 'redirects to joinmastodon site' do

View file

@ -23,12 +23,19 @@ RSpec.describe HomeHelper do
context 'with a valid account' do
let(:account) { Fabricate(:account) }
it 'returns a link to the account' do
without_partial_double_verification do
allow(helper).to receive_messages(current_account: account, prefers_autoplay?: false)
result = helper.account_link_to(account)
before { helper.extend controller_helpers }
expect(result).to match "@#{account.acct}"
it 'returns a link to the account' do
result = helper.account_link_to(account)
expect(result).to match "@#{account.acct}"
end
private
def controller_helpers
Module.new do
def current_account = Account.last
end
end
end

View file

@ -3,16 +3,12 @@
require 'rails_helper'
describe MediaComponentHelper do
before { helper.extend controller_helpers }
describe 'render_video_component' do
let(:media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status)) }
let(:result) { helper.render_video_component(media.status) }
before do
without_partial_double_verification do
allow(helper).to receive(:current_account).and_return(media.account)
end
end
it 'renders a react component for the video' do
expect(parsed_html.div['data-component']).to eq('Video')
end
@ -22,12 +18,6 @@ describe MediaComponentHelper do
let(:media) { Fabricate(:media_attachment, type: :audio, status: Fabricate(:status)) }
let(:result) { helper.render_audio_component(media.status) }
before do
without_partial_double_verification do
allow(helper).to receive(:current_account).and_return(media.account)
end
end
it 'renders a react component for the audio' do
expect(parsed_html.div['data-component']).to eq('Audio')
end
@ -37,12 +27,6 @@ describe MediaComponentHelper do
let(:media) { Fabricate(:media_attachment, type: :audio, status: Fabricate(:status)) }
let(:result) { helper.render_media_gallery_component(media.status) }
before do
without_partial_double_verification do
allow(helper).to receive(:current_account).and_return(media.account)
end
end
it 'renders a react component for the media gallery' do
expect(parsed_html.div['data-component']).to eq('MediaGallery')
end
@ -54,10 +38,6 @@ describe MediaComponentHelper do
before do
PreviewCardsStatus.create(status: status, preview_card: Fabricate(:preview_card))
without_partial_double_verification do
allow(helper).to receive(:current_account).and_return(status.account)
end
end
it 'returns the correct react component markup' do
@ -69,12 +49,6 @@ describe MediaComponentHelper do
let(:status) { Fabricate(:status, poll: Fabricate(:poll)) }
let(:result) { helper.render_poll_component(status) }
before do
without_partial_double_verification do
allow(helper).to receive(:current_account).and_return(status.account)
end
end
it 'returns the correct react component markup' do
expect(parsed_html.div['data-component']).to eq('Poll')
end
@ -85,4 +59,10 @@ describe MediaComponentHelper do
def parsed_html
Nokogiri::Slop(result)
end
def controller_helpers
Module.new do
def current_account = Account.last
end
end
end

File diff suppressed because it is too large Load diff

View file

@ -4,22 +4,29 @@ require 'rails_helper'
require 'mastodon/cli/cache'
describe Mastodon::CLI::Cache do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#clear' do
let(:action) { :clear }
before { allow(Rails.cache).to receive(:clear) }
it 'clears the Rails cache' do
expect { cli.invoke(:clear) }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
expect(Rails.cache).to have_received(:clear)
end
end
describe '#recount' do
let(:action) { :recount }
context 'with the `accounts` argument' do
let(:arguments) { ['accounts'] }
let(:account_stat) { Fabricate(:account_stat) }
@ -29,9 +36,8 @@ describe Mastodon::CLI::Cache do
end
it 're-calculates account records in the cache' do
expect { cli.invoke(:recount, arguments) }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
expect(account_stat.reload.statuses_count).to be_zero
end
@ -46,9 +52,8 @@ describe Mastodon::CLI::Cache do
end
it 're-calculates account records in the cache' do
expect { cli.invoke(:recount, arguments) }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
expect(status_stat.reload.replies_count).to be_zero
end
@ -58,9 +63,9 @@ describe Mastodon::CLI::Cache do
let(:arguments) { ['other-type'] }
it 'Exits with an error message' do
expect { cli.invoke(:recount, arguments) }.to output(
a_string_including('Unknown')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('Unknown')
.and raise_error(SystemExit)
end
end
end

View file

@ -4,42 +4,45 @@ require 'rails_helper'
require 'mastodon/cli/canonical_email_blocks'
describe Mastodon::CLI::CanonicalEmailBlocks do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#find' do
let(:action) { :find }
let(:arguments) { ['user@example.com'] }
context 'when a block is present' do
before { Fabricate(:canonical_email_block, email: 'user@example.com') }
it 'announces the presence of the block' do
expect { cli.invoke(:find, arguments) }.to output(
a_string_including('user@example.com is blocked')
).to_stdout
expect { subject }
.to output_results('user@example.com is blocked')
end
end
context 'when a block is not present' do
it 'announces the absence of the block' do
expect { cli.invoke(:find, arguments) }.to output(
a_string_including('user@example.com is not blocked')
).to_stdout
expect { subject }
.to output_results('user@example.com is not blocked')
end
end
end
describe '#remove' do
let(:action) { :remove }
let(:arguments) { ['user@example.com'] }
context 'when a block is present' do
before { Fabricate(:canonical_email_block, email: 'user@example.com') }
it 'removes the block' do
expect { cli.invoke(:remove, arguments) }.to output(
a_string_including('Unblocked user@example.com')
).to_stdout
expect { subject }
.to output_results('Unblocked user@example.com')
expect(CanonicalEmailBlock.matching_email('user@example.com')).to be_empty
end
@ -47,9 +50,8 @@ describe Mastodon::CLI::CanonicalEmailBlocks do
context 'when a block is not present' do
it 'announces the absence of the block' do
expect { cli.invoke(:remove, arguments) }.to output(
a_string_including('user@example.com is not blocked')
).to_stdout
expect { subject }
.to output_results('user@example.com is not blocked')
end
end
end

View file

@ -4,22 +4,75 @@ require 'rails_helper'
require 'mastodon/cli/domains'
describe Mastodon::CLI::Domains do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#purge' do
let(:action) { :purge }
context 'with accounts from the domain' do
let(:options) { {} }
let(:domain) { 'host.example' }
let!(:account) { Fabricate(:account, domain: domain) }
let(:arguments) { [domain] }
it 'removes the account' do
expect { cli.invoke(:purge, [domain], options) }.to output(
a_string_including('Removed 1 accounts')
).to_stdout
expect { subject }
.to output_results('Removed 1 accounts')
expect { account.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
describe '#crawl' do
let(:action) { :crawl }
context 'with accounts from the domain' do
let(:domain) { 'host.example' }
before do
Fabricate(:account, domain: domain)
stub_request(:get, 'https://host.example/api/v1/instance').to_return(status: 200, body: {}.to_json)
stub_request(:get, 'https://host.example/api/v1/instance/peers').to_return(status: 200, body: {}.to_json)
stub_request(:get, 'https://host.example/api/v1/instance/activity').to_return(status: 200, body: {}.to_json)
stub_const('Mastodon::CLI::Domains::CRAWL_SLEEP_TIME', 0)
end
context 'with --format of summary' do
let(:options) { { format: 'summary' } }
it 'crawls the domains and summarizes results' do
expect { subject }
.to output_results('Visited 1 domains, 0 failed')
end
end
context 'with --format of domains' do
let(:options) { { format: 'domains' } }
it 'crawls the domains and summarizes results' do
expect { subject }
.to output_results(domain)
end
end
context 'with --format of json' do
let(:options) { { format: 'json' } }
it 'crawls the domains and summarizes results' do
expect { subject }
.to output_results(json_summary)
end
def json_summary
Oj.dump('host.example': { activity: {} })
end
end
end
end
end

View file

@ -4,96 +4,99 @@ require 'rails_helper'
require 'mastodon/cli/email_domain_blocks'
describe Mastodon::CLI::EmailDomainBlocks do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#list' do
let(:action) { :list }
context 'with email domain block records' do
let!(:parent_block) { Fabricate(:email_domain_block) }
let!(:child_block) { Fabricate(:email_domain_block, parent: parent_block) }
let(:options) { {} }
it 'lists the blocks' do
expect { cli.invoke(:list, [], options) }.to output(
a_string_including(parent_block.domain)
.and(a_string_including(child_block.domain))
).to_stdout
expect { subject }
.to output_results(
parent_block.domain,
child_block.domain
)
end
end
end
describe '#add' do
context 'without any options' do
let(:options) { {} }
let(:action) { :add }
context 'without any options' do
it 'warns about usage and exits' do
expect { cli.invoke(:add, [], options) }.to output(
a_string_including('No domain(s) given')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('No domain(s) given')
.and raise_error(SystemExit)
end
end
context 'when blocks exist' do
let(:options) { {} }
let(:domain) { 'host.example' }
let(:arguments) { [domain] }
before { Fabricate(:email_domain_block, domain: domain) }
it 'does not add a new block' do
expect { cli.invoke(:add, [domain], options) }.to output(
a_string_including('is already blocked')
).to_stdout
expect { subject }
.to output_results('is already blocked')
.and(not_change(EmailDomainBlock, :count))
end
end
context 'when no blocks exist' do
let(:options) { {} }
let(:domain) { 'host.example' }
let(:arguments) { [domain] }
it 'adds a new block' do
expect { cli.invoke(:add, [domain], options) }.to output(
a_string_including('Added 1')
).to_stdout
expect { subject }
.to output_results('Added 1')
.and(change(EmailDomainBlock, :count).by(1))
end
end
end
describe '#remove' do
context 'without any options' do
let(:options) { {} }
let(:action) { :remove }
context 'without any options' do
it 'warns about usage and exits' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('No domain(s) given')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('No domain(s) given')
.and raise_error(SystemExit)
end
end
context 'when blocks exist' do
let(:options) { {} }
let(:domain) { 'host.example' }
let(:arguments) { [domain] }
before { Fabricate(:email_domain_block, domain: domain) }
it 'removes the block' do
expect { cli.invoke(:remove, [domain], options) }.to output(
a_string_including('Removed 1')
).to_stdout
expect { subject }
.to output_results('Removed 1')
.and(change(EmailDomainBlock, :count).by(-1))
end
end
context 'when no blocks exist' do
let(:options) { {} }
let(:domain) { 'host.example' }
let(:arguments) { [domain] }
it 'does not remove a block' do
expect { cli.invoke(:remove, [domain], options) }.to output(
a_string_including('is not yet blocked')
).to_stdout
expect { subject }
.to output_results('is not yet blocked')
.and(not_change(EmailDomainBlock, :count))
end
end

View file

@ -4,5 +4,61 @@ require 'rails_helper'
require 'mastodon/cli/emoji'
describe Mastodon::CLI::Emoji do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#purge' do
let(:action) { :purge }
context 'with existing custom emoji' do
before { Fabricate(:custom_emoji) }
it 'reports a successful purge' do
expect { subject }
.to output_results('OK')
end
end
end
describe '#import' do
context 'with existing custom emoji' do
let(:import_path) { Rails.root.join('spec', 'fixtures', 'files', 'elite-assets.tar.gz') }
let(:action) { :import }
let(:arguments) { [import_path] }
it 'reports about imported emoji' do
expect { subject }
.to output_results('Imported 1')
.and change(CustomEmoji, :count).by(1)
end
end
end
describe '#export' do
context 'with existing custom emoji' do
before do
FileUtils.rm_rf(export_path.dirname)
FileUtils.mkdir_p(export_path.dirname)
Fabricate(:custom_emoji)
end
after { FileUtils.rm_rf(export_path.dirname) }
let(:export_path) { Rails.root.join('tmp', 'cli-tests', 'export.tar.gz') }
let(:arguments) { [export_path.dirname.to_s] }
let(:action) { :export }
it 'reports about exported emoji' do
expect { subject }
.to output_results('Exported 1')
.and change { File.exist?(export_path) }.from(false).to(true)
end
end
end
end

View file

@ -4,20 +4,25 @@ require 'rails_helper'
require 'mastodon/cli/feeds'
describe Mastodon::CLI::Feeds do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#build' do
let(:action) { :build }
before { Fabricate(:account) }
context 'with --all option' do
let(:options) { { all: true } }
it 'regenerates feeds for all accounts' do
expect { cli.invoke(:build, [], options) }.to output(
a_string_including('Regenerated feeds')
).to_stdout
expect { subject }
.to output_results('Regenerated feeds')
end
end
@ -27,9 +32,8 @@ describe Mastodon::CLI::Feeds do
let(:arguments) { ['alice'] }
it 'regenerates feeds for the account' do
expect { cli.invoke(:build, arguments) }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
end
end
@ -37,22 +41,23 @@ describe Mastodon::CLI::Feeds do
let(:arguments) { ['invalid-username'] }
it 'displays an error and exits' do
expect { cli.invoke(:build, arguments) }.to output(
a_string_including('No such account')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
end
end
end
describe '#clear' do
let(:action) { :clear }
before do
allow(redis).to receive(:del).with(key_namespace)
end
it 'clears the redis `feed:*` namespace' do
expect { cli.invoke(:clear) }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
expect(redis).to have_received(:del).with(key_namespace).once
end

View file

@ -4,11 +4,16 @@ require 'rails_helper'
require 'mastodon/cli/ip_blocks'
describe Mastodon::CLI::IpBlocks do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#add' do
let(:action) { :add }
let(:ip_list) do
[
'192.0.2.1',
@ -25,10 +30,11 @@ describe Mastodon::CLI::IpBlocks do
]
end
let(:options) { { severity: 'no_access' } }
let(:arguments) { ip_list }
shared_examples 'ip address blocking' do
it 'blocks all specified IP addresses' do
cli.invoke(:add, ip_list, options)
subject
blocked_ip_addresses = IpBlock.where(ip: ip_list).pluck(:ip)
expected_ip_addresses = ip_list.map { |ip| IPAddr.new(ip) }
@ -37,7 +43,7 @@ describe Mastodon::CLI::IpBlocks do
end
it 'sets the severity for all blocked IP addresses' do
cli.invoke(:add, ip_list, options)
subject
blocked_ips_severity = IpBlock.where(ip: ip_list).pluck(:severity).all?(options[:severity])
@ -45,9 +51,8 @@ describe Mastodon::CLI::IpBlocks do
end
it 'displays a success message with a summary' do
expect { cli.invoke(:add, ip_list, options) }.to output(
a_string_including("Added #{ip_list.size}, skipped 0, failed 0")
).to_stdout
expect { subject }
.to output_results("Added #{ip_list.size}, skipped 0, failed 0")
end
end
@ -57,19 +62,19 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address is already blocked' do
let!(:blocked_ip) { IpBlock.create(ip: ip_list.last, severity: options[:severity]) }
let(:arguments) { ip_list }
it 'skips the already blocked IP address' do
allow(IpBlock).to receive(:new).and_call_original
cli.invoke(:add, ip_list, options)
subject
expect(IpBlock).to_not have_received(:new).with(ip: ip_list.last)
end
it 'displays the correct summary' do
expect { cli.invoke(:add, ip_list, options) }.to output(
a_string_including("#{ip_list.last} is already blocked\nAdded #{ip_list.size - 1}, skipped 1, failed 0")
).to_stdout
expect { subject }
.to output_results("#{ip_list.last} is already blocked\nAdded #{ip_list.size - 1}, skipped 1, failed 0")
end
context 'with --force option' do
@ -77,7 +82,7 @@ describe Mastodon::CLI::IpBlocks do
let(:options) { { severity: 'sign_up_requires_approval', force: true } }
it 'overwrites the existing IP block record' do
expect { cli.invoke(:add, ip_list, options) }
expect { subject }
.to change { blocked_ip.reload.severity }
.from('no_access')
.to('sign_up_requires_approval')
@ -89,11 +94,11 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address is invalid' do
let(:ip_list) { ['320.15.175.0', '9.5.105.255', '0.0.0.0'] }
let(:arguments) { ip_list }
it 'displays the correct summary' do
expect { cli.invoke(:add, ip_list, options) }.to output(
a_string_including("#{ip_list.first} is invalid\nAdded #{ip_list.size - 1}, skipped 0, failed 1")
).to_stdout
expect { subject }
.to output_results("#{ip_list.first} is invalid\nAdded #{ip_list.size - 1}, skipped 0, failed 1")
end
end
@ -124,6 +129,7 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address fails to be blocked' do
let(:ip_address) { '127.0.0.1' }
let(:ip_block) { instance_double(IpBlock, ip: ip_address, save: false) }
let(:arguments) { [ip_address] }
before do
allow(IpBlock).to receive(:new).and_return(ip_block)
@ -132,24 +138,25 @@ describe Mastodon::CLI::IpBlocks do
end
it 'displays an error message' do
expect { cli.invoke(:add, [ip_address], options) }
.to output(
a_string_including("#{ip_address} could not be saved")
).to_stdout
expect { subject }
.to output_results("#{ip_address} could not be saved")
end
end
context 'when no IP address is provided' do
let(:arguments) { [] }
it 'exits with an error message' do
expect { cli.add }.to output(
a_string_including('No IP(s) given')
).to_stdout
expect { subject }
.to output_results('No IP(s) given')
.and raise_error(SystemExit)
end
end
end
describe '#remove' do
let(:action) { :remove }
context 'when removing exact matches' do
let(:ip_list) do
[
@ -166,21 +173,21 @@ describe Mastodon::CLI::IpBlocks do
'::/128',
]
end
let(:arguments) { ip_list }
before do
ip_list.each { |ip| IpBlock.create(ip: ip, severity: :no_access) }
end
it 'removes exact IP blocks' do
cli.invoke(:remove, ip_list)
subject
expect(IpBlock.where(ip: ip_list)).to_not exist
end
it 'displays success message with a summary' do
expect { cli.invoke(:remove, ip_list) }.to output(
a_string_including("Removed #{ip_list.size}, skipped 0")
).to_stdout
expect { subject }
.to output_results("Removed #{ip_list.size}, skipped 0")
end
end
@ -192,13 +199,13 @@ describe Mastodon::CLI::IpBlocks do
let(:options) { { force: true } }
it 'removes blocks for IP ranges that cover given IP(s)' do
cli.invoke(:remove, arguments, options)
subject
expect(IpBlock.where(id: [first_ip_range_block.id, second_ip_range_block.id])).to_not exist
end
it 'does not remove other IP ranges' do
cli.invoke(:remove, arguments, options)
subject
expect(IpBlock.where(id: third_ip_range_block.id)).to exist
end
@ -206,47 +213,46 @@ describe Mastodon::CLI::IpBlocks do
context 'when a specified IP address is not blocked' do
let(:unblocked_ip) { '192.0.2.1' }
let(:arguments) { [unblocked_ip] }
it 'skips the IP address' do
expect { cli.invoke(:remove, [unblocked_ip]) }.to output(
a_string_including("#{unblocked_ip} is not yet blocked")
).to_stdout
expect { subject }
.to output_results("#{unblocked_ip} is not yet blocked")
end
it 'displays the summary correctly' do
expect { cli.invoke(:remove, [unblocked_ip]) }.to output(
a_string_including('Removed 0, skipped 1')
).to_stdout
expect { subject }
.to output_results('Removed 0, skipped 1')
end
end
context 'when a specified IP address is invalid' do
let(:invalid_ip) { '320.15.175.0' }
let(:arguments) { [invalid_ip] }
it 'skips the invalid IP address' do
expect { cli.invoke(:remove, [invalid_ip]) }.to output(
a_string_including("#{invalid_ip} is invalid")
).to_stdout
expect { subject }
.to output_results("#{invalid_ip} is invalid")
end
it 'displays the summary correctly' do
expect { cli.invoke(:remove, [invalid_ip]) }.to output(
a_string_including('Removed 0, skipped 1')
).to_stdout
expect { subject }
.to output_results('Removed 0, skipped 1')
end
end
context 'when no IP address is provided' do
it 'exits with an error message' do
expect { cli.remove }.to output(
a_string_including('No IP(s) given')
).to_stdout
expect { subject }
.to output_results('No IP(s) given')
.and raise_error(SystemExit)
end
end
end
describe '#export' do
let(:action) { :export }
let(:first_ip_range_block) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) }
let(:second_ip_range_block) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) }
let(:third_ip_range_block) { IpBlock.create(ip: '127.0.0.1', severity: :sign_up_block) }
@ -255,15 +261,13 @@ describe Mastodon::CLI::IpBlocks do
let(:options) { { format: 'plain' } }
it 'exports blocked IPs with "no_access" severity in plain format' do
expect { cli.invoke(:export, nil, options) }.to output(
a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
).to_stdout
expect { subject }
.to output_results("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
end
it 'does not export bloked IPs with different severities' do
expect { cli.invoke(:export, nil, options) }.to_not output(
a_string_including("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
).to_stdout
expect { subject }
.to_not output_results("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
end
end
@ -271,23 +275,20 @@ describe Mastodon::CLI::IpBlocks do
let(:options) { { format: 'nginx' } }
it 'exports blocked IPs with "no_access" severity in plain format' do
expect { cli.invoke(:export, nil, options) }.to output(
a_string_including("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
).to_stdout
expect { subject }
.to output_results("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
end
it 'does not export bloked IPs with different severities' do
expect { cli.invoke(:export, nil, options) }.to_not output(
a_string_including("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
).to_stdout
expect { subject }
.to_not output_results("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
end
end
context 'when --format option is not provided' do
it 'exports blocked IPs in plain format by default' do
expect { cli.export }.to output(
a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
).to_stdout
expect { subject }
.to output_results("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
end
end
end

View file

@ -4,13 +4,20 @@ require 'rails_helper'
require 'mastodon/cli/main'
describe Mastodon::CLI::Main do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe 'version' do
describe '#version' do
let(:action) { :version }
it 'returns the Mastodon version' do
expect { described_class.new.invoke(:version) }.to output(
a_string_including(Mastodon::Version.to_s)
).to_stdout
expect { subject }
.to output_results(Mastodon::Version.to_s)
end
end
end

View file

@ -4,20 +4,26 @@ require 'rails_helper'
require 'mastodon/cli/maintenance'
describe Mastodon::CLI::Maintenance do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#fix_duplicates' do
let(:action) { :fix_duplicates }
context 'when the database version is too old' do
before do
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(2000_01_01_000000) # Earlier than minimum
end
it 'Exits with error message' do
expect { cli.invoke :fix_duplicates }.to output(
a_string_including('is too old')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('is too old')
.and raise_error(SystemExit)
end
end
@ -28,9 +34,9 @@ describe Mastodon::CLI::Maintenance do
end
it 'Exits with error message' do
expect { cli.invoke :fix_duplicates }.to output(
a_string_including('more recent')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('more recent')
.and raise_error(SystemExit)
end
end
@ -41,9 +47,9 @@ describe Mastodon::CLI::Maintenance do
end
it 'Exits with error message' do
expect { cli.invoke :fix_duplicates }.to output(
a_string_including('Sidekiq is running')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('Sidekiq is running')
.and raise_error(SystemExit)
end
end
end

View file

@ -4,18 +4,24 @@ require 'rails_helper'
require 'mastodon/cli/media'
describe Mastodon::CLI::Media do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#remove' do
let(:action) { :remove }
context 'with --prune-profiles and --remove-headers' do
let(:options) { { prune_profiles: true, remove_headers: true } }
it 'warns about usage and exits' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('--prune-profiles and --remove-headers should not be specified simultaneously')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('--prune-profiles and --remove-headers should not be specified simultaneously')
.and raise_error(SystemExit)
end
end
@ -23,9 +29,9 @@ describe Mastodon::CLI::Media do
let(:options) { { include_follows: true } }
it 'warns about usage and exits' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('--include-follows can only be used with --prune-profiles or --remove-headers')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('--include-follows can only be used with --prune-profiles or --remove-headers')
.and raise_error(SystemExit)
end
end
@ -38,9 +44,8 @@ describe Mastodon::CLI::Media do
let(:options) { { prune_profiles: true } }
it 'removes account avatars' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('Visited 1')
).to_stdout
expect { subject }
.to output_results('Visited 1')
expect(account.reload.avatar).to be_blank
end
@ -50,9 +55,8 @@ describe Mastodon::CLI::Media do
let(:options) { { remove_headers: true } }
it 'removes account header' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('Visited 1')
).to_stdout
expect { subject }
.to output_results('Visited 1')
expect(account.reload.header).to be_blank
end
@ -64,9 +68,8 @@ describe Mastodon::CLI::Media do
context 'without options' do
it 'removes account avatars' do
expect { cli.invoke(:remove) }.to output(
a_string_including('Removed 1')
).to_stdout
expect { subject }
.to output_results('Removed 1')
expect(media_attachment.reload.file).to be_blank
expect(media_attachment.reload.thumbnail).to be_blank
@ -76,25 +79,50 @@ describe Mastodon::CLI::Media do
end
describe '#usage' do
context 'without options' do
let(:options) { {} }
let(:action) { :usage }
context 'without options' do
it 'reports about storage size' do
expect { cli.invoke(:usage, [], options) }.to output(
a_string_including('0 Bytes')
).to_stdout
expect { subject }
.to output_results('0 Bytes')
end
end
end
describe '#lookup' do
let(:action) { :lookup }
let(:arguments) { [url] }
context 'with valid url not connected to a record' do
let(:url) { 'https://example.host/assets/1' }
it 'warns about url and exits' do
expect { subject }
.to output_results('Not a media URL')
.and raise_error(SystemExit)
end
end
context 'with a valid media url' do
let(:status) { Fabricate(:status) }
let(:media_attachment) { Fabricate(:media_attachment, status: status) }
let(:url) { media_attachment.file.url(:original) }
it 'displays the url of a connected status' do
expect { subject }
.to output_results(status.id.to_s)
end
end
end
describe '#refresh' do
context 'without any options' do
let(:options) { {} }
let(:action) { :refresh }
context 'without any options' do
it 'warns about usage and exits' do
expect { cli.invoke(:refresh, [], options) }.to output(
a_string_including('Specify the source')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('Specify the source')
.and raise_error(SystemExit)
end
end
@ -108,9 +136,8 @@ describe Mastodon::CLI::Media do
let(:status) { Fabricate(:status) }
it 'redownloads the attachment file' do
expect { cli.invoke(:refresh, [], options) }.to output(
a_string_including('Downloaded 1 media')
).to_stdout
expect { subject }
.to output_results('Downloaded 1 media')
end
end
@ -119,9 +146,9 @@ describe Mastodon::CLI::Media do
let(:options) { { account: 'not-real-user@example.host' } }
it 'warns about usage and exits' do
expect { cli.invoke(:refresh, [], options) }.to output(
a_string_including('No such account')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('No such account')
.and raise_error(SystemExit)
end
end
@ -135,9 +162,8 @@ describe Mastodon::CLI::Media do
let(:account) { Fabricate(:account) }
it 'redownloads the attachment file' do
expect { cli.invoke(:refresh, [], options) }.to output(
a_string_including('Downloaded 1 media')
).to_stdout
expect { subject }
.to output_results('Downloaded 1 media')
end
end
end
@ -153,9 +179,8 @@ describe Mastodon::CLI::Media do
let(:account) { Fabricate(:account, domain: domain) }
it 'redownloads the attachment file' do
expect { cli.invoke(:refresh, [], options) }.to output(
a_string_including('Downloaded 1 media')
).to_stdout
expect { subject }
.to output_results('Downloaded 1 media')
end
end
end

View file

@ -4,11 +4,17 @@ require 'rails_helper'
require 'mastodon/cli/preview_cards'
describe Mastodon::CLI::PreviewCards do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#remove' do
let(:action) { :remove }
context 'with relevant preview cards' do
before do
Fabricate(:preview_card, updated_at: 10.years.ago, type: :link)
@ -18,10 +24,11 @@ describe Mastodon::CLI::PreviewCards do
context 'with no arguments' do
it 'deletes thumbnails for local preview cards' do
expect { cli.invoke(:remove) }.to output(
a_string_including('Removed 2 preview cards')
.and(a_string_including('approx. 119 KB'))
).to_stdout
expect { subject }
.to output_results(
'Removed 2 preview cards',
'approx. 119 KB'
)
end
end
@ -29,10 +36,11 @@ describe Mastodon::CLI::PreviewCards do
let(:options) { { link: true } }
it 'deletes thumbnails for local preview cards' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('Removed 1 link-type preview cards')
.and(a_string_including('approx. 59.6 KB'))
).to_stdout
expect { subject }
.to output_results(
'Removed 1 link-type preview cards',
'approx. 59.6 KB'
)
end
end
@ -40,10 +48,11 @@ describe Mastodon::CLI::PreviewCards do
let(:options) { { days: 365 } }
it 'deletes thumbnails for local preview cards' do
expect { cli.invoke(:remove, [], options) }.to output(
a_string_including('Removed 1 preview cards')
.and(a_string_including('approx. 59.6 KB'))
).to_stdout
expect { subject }
.to output_results(
'Removed 1 preview cards',
'approx. 59.6 KB'
)
end
end
end

View file

@ -4,5 +4,79 @@ require 'rails_helper'
require 'mastodon/cli/search'
describe Mastodon::CLI::Search do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#deploy' do
let(:action) { :deploy }
context 'with concurrency out of range' do
let(:options) { { concurrency: -100 } }
it 'Exits with error message' do
expect { subject }
.to output_results('this concurrency setting')
.and raise_error(SystemExit)
end
end
context 'with batch size out of range' do
let(:options) { { batch_size: -100_000 } }
it 'Exits with error message' do
expect { subject }
.to output_results('this batch_size setting')
.and raise_error(SystemExit)
end
end
context 'without options' do
before { stub_search_indexes }
let(:indexed_count) { 1 }
let(:deleted_count) { 2 }
it 'reports about storage size' do
expect { subject }
.to output_results(
"Indexed #{described_class::INDICES.size * indexed_count} records",
"de-indexed #{described_class::INDICES.size * deleted_count}"
)
end
end
def stub_search_indexes
described_class::INDICES.each do |index|
allow(index)
.to receive_messages(
specification: instance_double(Chewy::Index::Specification, changed?: true, lock!: nil),
purge: nil
)
importer_double = importer_double_for(index)
allow(importer_double).to receive(:on_progress).and_yield([indexed_count, deleted_count])
allow("Importer::#{index}Importer".constantize)
.to receive(:new)
.and_return(importer_double)
end
end
def importer_double_for(index)
instance_double(
"Importer::#{index}Importer".constantize,
clean_up!: nil,
estimate!: 100,
import!: nil,
on_failure: nil,
# on_progress: nil,
optimize_for_import!: nil,
optimize_for_search!: nil
)
end
end
end

View file

@ -7,59 +7,64 @@ describe Mastodon::CLI::Settings do
it_behaves_like 'CLI Command'
describe 'subcommand "registrations"' do
subject { cli.invoke(action, arguments, options) }
let(:cli) { Mastodon::CLI::Registrations.new }
let(:arguments) { [] }
let(:options) { {} }
before do
Setting.registrations_mode = nil
end
describe '#open' do
let(:action) { :open }
it 'changes "registrations_mode" to "open"' do
expect { cli.open }.to change(Setting, :registrations_mode).from(nil).to('open')
expect { subject }.to change(Setting, :registrations_mode).from(nil).to('open')
end
it 'displays success message' do
expect { cli.open }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
end
end
describe '#approved' do
let(:action) { :approved }
it 'changes "registrations_mode" to "approved"' do
expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
expect { subject }.to change(Setting, :registrations_mode).from(nil).to('approved')
end
it 'displays success message' do
expect { cli.approved }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
end
context 'with --require-reason' do
before do
cli.options = { require_reason: true }
end
let(:options) { { require_reason: true } }
it 'changes "registrations_mode" to "approved"' do
expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
expect { subject }.to change(Setting, :registrations_mode).from(nil).to('approved')
end
it 'sets "require_invite_text" to "true"' do
expect { cli.approved }.to change(Setting, :require_invite_text).from(false).to(true)
expect { subject }.to change(Setting, :require_invite_text).from(false).to(true)
end
end
end
describe '#close' do
let(:action) { :close }
it 'changes "registrations_mode" to "none"' do
expect { cli.close }.to change(Setting, :registrations_mode).from(nil).to('none')
expect { subject }.to change(Setting, :registrations_mode).from(nil).to('none')
end
it 'displays success message' do
expect { cli.close }.to output(
a_string_including('OK')
).to_stdout
expect { subject }
.to output_results('OK')
end
end
end

View file

@ -4,26 +4,31 @@ require 'rails_helper'
require 'mastodon/cli/statuses'
describe Mastodon::CLI::Statuses do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#remove', use_transactional_tests: false do
let(:action) { :remove }
context 'with small batch size' do
let(:options) { { batch_size: 0 } }
it 'exits with error message' do
expect { cli.invoke :remove, [], options }.to output(
a_string_including('Cannot run')
).to_stdout.and raise_error(SystemExit)
expect { subject }
.to output_results('Cannot run')
.and raise_error(SystemExit)
end
end
context 'with default batch size' do
it 'removes unreferenced statuses' do
expect { cli.invoke :remove }.to output(
a_string_including('Done after')
).to_stdout
expect { subject }
.to output_results('Done after')
end
end
end

View file

@ -4,23 +4,26 @@ require 'rails_helper'
require 'mastodon/cli/upgrade'
describe Mastodon::CLI::Upgrade do
subject { cli.invoke(action, arguments, options) }
let(:cli) { described_class.new }
let(:arguments) { [] }
let(:options) { {} }
it_behaves_like 'CLI Command'
describe '#storage_schema' do
context 'with records that dont need upgrading' do
let(:options) { {} }
let(:action) { :storage_schema }
context 'with records that dont need upgrading' do
before do
Fabricate(:account)
Fabricate(:media_attachment)
end
it 'does not upgrade storage for the attachments' do
expect { cli.invoke(:storage_schema, [], options) }.to output(
a_string_including('Upgraded storage schema of 0 records')
).to_stdout
expect { subject }
.to output_results('Upgraded storage schema of 0 records')
end
end
end

View file

@ -88,6 +88,7 @@ RSpec.configure do |config|
config.include Chewy::Rspec::Helpers
config.include Redisable
config.include SignedRequestHelpers, type: :request
config.include CommandLineHelpers, type: :cli
config.around(:each, use_transactional_tests: false) do |example|
self.use_transactional_tests = false

View file

@ -2,25 +2,21 @@
require 'rails_helper'
RSpec.describe Api::V2::SearchController do
render_views
describe 'Search API' do
context 'with token' do
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
let(:user) { Fabricate(:user) }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
let(:scopes) { 'read:search' }
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
before do
allow(controller).to receive(:doorkeeper_token) { token }
end
describe 'GET #index' do
describe 'GET /api/v2/search' do
let!(:bob) { Fabricate(:account, username: 'bob_test') }
let!(:ana) { Fabricate(:account, username: 'ana_test') }
let!(:tom) { Fabricate(:account, username: 'tom_test') }
let(:params) { { q: 'test' } }
it 'returns http success' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
end
@ -29,7 +25,7 @@ RSpec.describe Api::V2::SearchController do
let(:params) { { q: 'test', type: 'accounts' } }
it 'returns all matching accounts' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s)
end
@ -38,7 +34,7 @@ RSpec.describe Api::V2::SearchController do
let(:params) { { q: 'test1', resolve: '1' } }
it 'returns http unauthorized' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
end
@ -48,7 +44,7 @@ RSpec.describe Api::V2::SearchController do
let(:params) { { q: 'test1', offset: 1 } }
it 'returns http unauthorized' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(200)
end
@ -62,7 +58,7 @@ RSpec.describe Api::V2::SearchController do
end
it 'returns only the followed accounts' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(ana.id.to_s)
end
@ -73,7 +69,7 @@ RSpec.describe Api::V2::SearchController do
before { allow(Search).to receive(:new).and_raise(Mastodon::SyntaxError) }
it 'returns http unprocessable_entity' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(422)
end
@ -83,7 +79,7 @@ RSpec.describe Api::V2::SearchController do
before { allow(Search).to receive(:new).and_raise(ActiveRecord::RecordNotFound) }
it 'returns http not_found' do
get :index, params: params
get '/api/v2/search', headers: headers, params: params
expect(response).to have_http_status(404)
end
@ -92,11 +88,11 @@ RSpec.describe Api::V2::SearchController do
end
context 'without token' do
describe 'GET #index' do
describe 'GET /api/v2/search' do
let(:search_params) { nil }
before do
get :index, params: search_params
get '/api/v2/search', params: search_params
end
context 'without a `q` param' do

View file

@ -378,12 +378,10 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
end
end
it 'creates at least some accounts' do
expect { subject }.to change { Account.remote.count }.by_at_least(2)
end
it 'creates no more account than the limit allows' do
expect { subject }.to change { Account.remote.count }.by_at_most(5)
it 'creates accounts without exceeding rate limit' do
expect { subject }
.to create_some_remote_accounts
.and create_fewer_than_rate_limit_accounts
end
end
@ -445,12 +443,20 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
end
end
it 'creates at least some accounts' do
expect { subject.call('user1', 'foo.test', payload) }.to change { Account.remote.count }.by_at_least(2)
end
it 'creates no more account than the limit allows' do
expect { subject.call('user1', 'foo.test', payload) }.to change { Account.remote.count }.by_at_most(5)
it 'creates accounts without exceeding rate limit' do
expect { subject.call('user1', 'foo.test', payload) }
.to create_some_remote_accounts
.and create_fewer_than_rate_limit_accounts
end
end
private
def create_some_remote_accounts
change(Account.remote, :count).by_at_least(2)
end
def create_fewer_than_rate_limit_accounts
change(Account.remote, :count).by_at_most(5)
end
end

View file

@ -47,8 +47,15 @@ RSpec.describe DeleteAccountService, type: :service do
let!(:account_note) { Fabricate(:account_note, account: account) }
it 'deletes associated owned records' do
expect { subject }.to change {
it 'deletes associated owned and target records and target notifications' do
expect { subject }
.to delete_associated_owned_records
.and delete_associated_target_records
.and delete_associated_target_notifications
end
def delete_associated_owned_records
change do
[
account.statuses,
account.media_attachments,
@ -61,7 +68,7 @@ RSpec.describe DeleteAccountService, type: :service do
account.polls,
account.account_notes,
].map(&:count)
}.from([3, 1, 1, 1, 1, 1, 2, 2, 1, 1]).to([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
end.from([3, 1, 1, 1, 1, 1, 2, 2, 1, 1]).to([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
end
it 'deletes associated owned record groups' do
@ -82,20 +89,20 @@ RSpec.describe DeleteAccountService, type: :service do
expect { bookmark_category_status.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
it 'deletes associated target records' do
expect { subject }.to change {
def delete_associated_target_records
change do
[
AccountPin.where(target_account: account),
].map(&:count)
}.from([1]).to([0])
end.from([1]).to([0])
end
it 'deletes associated target notifications' do
expect { subject }.to change {
def delete_associated_target_notifications
change do
%w(
poll favourite emoji_reaction status mention follow
).map { |type| Notification.where(type: type).count }
}.from([1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0])
end.from([1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0])
end
end

View file

@ -18,14 +18,15 @@ RSpec.describe SuspendAccountService, type: :service do
account.suspend!
end
it "unmerges from local followers' feeds" do
subject
it 'unmerges from feeds of local followers and preserves suspended flag' do
expect { subject }
.to_not change_suspended_flag
expect(FeedManager.instance).to have_received(:unmerge_from_home).with(account, local_follower)
expect(FeedManager.instance).to have_received(:unmerge_from_list).with(account, list)
end
it 'does not change the “suspended” flag' do
expect { subject }.to_not change(account, :suspended?)
def change_suspended_flag
change(account, :suspended?)
end
end

View file

@ -45,14 +45,19 @@ RSpec.describe UnsuspendAccountService, type: :service do
remote_follower.follow!(account)
end
it "merges back into local followers' feeds" do
it 'merges back into feeds of local followers and sends update' do
subject
expect_feeds_merged
expect_updates_sent
end
def expect_feeds_merged
expect(FeedManager.instance).to have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to have_received(:merge_into_list).with(account, list)
end
it 'sends an update actor to followers and reporters' do
subject
def expect_updates_sent
expect(a_request(:post, remote_follower.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
expect(a_request(:post, remote_reporter.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
end
@ -73,19 +78,20 @@ RSpec.describe UnsuspendAccountService, type: :service do
allow(resolve_account_service).to receive(:call).with(account).and_return(account)
end
it 're-fetches the account' do
subject
it 're-fetches the account, merges feeds, and preserves suspended' do
expect { subject }
.to_not change_suspended_flag
expect_feeds_merged
expect(resolve_account_service).to have_received(:call).with(account)
end
it "merges back into local followers' feeds" do
subject
def expect_feeds_merged
expect(FeedManager.instance).to have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to have_received(:merge_into_list).with(account, list)
end
it 'does not change the “suspended” flag' do
expect { subject }.to_not change(account, :suspended?)
def change_suspended_flag
change(account, :suspended?)
end
end
@ -97,19 +103,20 @@ RSpec.describe UnsuspendAccountService, type: :service do
end
end
it 're-fetches the account' do
subject
it 're-fetches the account, does not merge feeds, marks suspended' do
expect { subject }
.to change_suspended_to_true
expect(resolve_account_service).to have_received(:call).with(account)
expect_feeds_not_merged
end
it "does not merge back into local followers' feeds" do
subject
def expect_feeds_not_merged
expect(FeedManager.instance).to_not have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to_not have_received(:merge_into_list).with(account, list)
end
it 'marks account as suspended' do
expect { subject }.to change(account, :suspended?).from(false).to(true)
def change_suspended_to_true
change(account, :suspended?).from(false).to(true)
end
end
@ -118,13 +125,14 @@ RSpec.describe UnsuspendAccountService, type: :service do
allow(resolve_account_service).to receive(:call).with(account).and_return(nil)
end
it 're-fetches the account' do
it 're-fetches the account and does not merge feeds' do
subject
expect(resolve_account_service).to have_received(:call).with(account)
expect_feeds_not_merged
end
it "does not merge back into local followers' feeds" do
subject
def expect_feeds_not_merged
expect(FeedManager.instance).to_not have_received(:merge_into_home).with(account, local_follower)
expect(FeedManager.instance).to_not have_received(:merge_into_list).with(account, list)
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
module CommandLineHelpers
def output_results(*args)
output(
include(*args)
).to_stdout
end
end

View file

@ -2390,7 +2390,7 @@ __metadata:
eslint-plugin-jsx-a11y: "npm:~6.8.0"
eslint-plugin-prettier: "npm:^5.0.0"
eslint-plugin-promise: "npm:~6.1.1"
eslint-plugin-react: "npm:~7.33.0"
eslint-plugin-react: "npm:^7.33.2"
eslint-plugin-react-hooks: "npm:^4.6.0"
file-loader: "npm:^6.2.0"
font-awesome: "npm:^4.7.0"
@ -5979,9 +5979,9 @@ __metadata:
linkType: hard
"core-js@npm:^3.30.2":
version: 3.33.3
resolution: "core-js@npm:3.33.3"
checksum: 08abdc9470c8228b9d09f61e62ab312738681202c4c34e9638889125b304b235f34c4fe22e9d41c20906ac0fcc807dca57c5ff7d6b90021bf64e8fe23461d9ab
version: 3.34.0
resolution: "core-js@npm:3.34.0"
checksum: 408a77898abe03bf3e5dec2a451c36f4745081cca9022f8bdf9b817d57bb6d3a534d555f47a4b95e1daa5e21dbc79122eac2402e25720d425f5925127e55dcd8
languageName: node
linkType: hard
@ -7529,7 +7529,7 @@ __metadata:
languageName: node
linkType: hard
"eslint-plugin-react@npm:~7.33.0":
"eslint-plugin-react@npm:^7.33.2":
version: 7.33.2
resolution: "eslint-plugin-react@npm:7.33.2"
dependencies:
@ -14698,8 +14698,8 @@ __metadata:
linkType: hard
"sass-loader@npm:^10.2.0":
version: 10.4.1
resolution: "sass-loader@npm:10.4.1"
version: 10.5.0
resolution: "sass-loader@npm:10.5.0"
dependencies:
klona: "npm:^2.0.4"
loader-utils: "npm:^2.0.0"
@ -14708,7 +14708,7 @@ __metadata:
semver: "npm:^7.3.2"
peerDependencies:
fibers: ">= 3.1.0"
node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
sass: ^1.3.0
webpack: ^4.36.0 || ^5.0.0
peerDependenciesMeta:
@ -14718,7 +14718,7 @@ __metadata:
optional: true
sass:
optional: true
checksum: bf04a440fe471928f3cf884bc12c6b70bc391795b35510b1b9021e8a2cca3b8f966aef9518f4171e87e9cb78193a774f695921e6b61881a1580ae0a3c7b1b5e4
checksum: be5da7784fd21c4f526cc3afaa1a765ba44cdc2f9798ecbac87b296ab44184ac5ba9bbda68a7a86f8cdcb6130acceefeb8912260fca14bdfc97f9dad02658400
languageName: node
linkType: hard