Compare commits

..

2 Commits

31 changed files with 66 additions and 205 deletions

View File

@@ -44,10 +44,7 @@ const Button = React.createClass({
cursor: 'pointer', cursor: 'pointer',
lineHeight: `${this.props.size}px`, lineHeight: `${this.props.size}px`,
borderRadius: '4px', borderRadius: '4px',
textDecoration: 'none', textDecoration: 'none'
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
overflow: 'hidden'
}; };
return ( return (

View File

@@ -48,7 +48,6 @@ import es from 'react-intl/locale-data/es';
import fi from 'react-intl/locale-data/fi'; import fi from 'react-intl/locale-data/fi';
import fr from 'react-intl/locale-data/fr'; import fr from 'react-intl/locale-data/fr';
import hu from 'react-intl/locale-data/hu'; import hu from 'react-intl/locale-data/hu';
import it from 'react-intl/locale-data/it';
import ja from 'react-intl/locale-data/ja'; import ja from 'react-intl/locale-data/ja';
import pt from 'react-intl/locale-data/pt'; import pt from 'react-intl/locale-data/pt';
import nl from 'react-intl/locale-data/nl'; import nl from 'react-intl/locale-data/nl';
@@ -79,7 +78,6 @@ addLocaleData([
...fi, ...fi,
...fr, ...fr,
...hu, ...hu,
...it,
...ja, ...ja,
...pt, ...pt,
...pt_br, ...pt_br,

View File

@@ -197,9 +197,9 @@ const ComposeForm = React.createClass({
<SpoilerButtonContainer /> <SpoilerButtonContainer />
</div> </div>
<div style={{ display: 'flex', minWidth: 0 }}> <div style={{ display: 'flex' }}>
<div style={{ paddingTop: '10px', marginRight: '16px', lineHeight: '36px' }}><CharacterCounter max={500} text={text} /></div> <div style={{ paddingTop: '10px', marginRight: '16px', lineHeight: '36px' }}><CharacterCounter max={500} text={text} /></div>
<div style={{ paddingTop: '10px', overflow: 'hidden' }}><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || text.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "_").length > 500} block /></div> <div style={{ paddingTop: '10px' }}><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || text.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "_").length > 500} /></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -53,7 +53,7 @@ const SearchResults = React.createClass({
return ( return (
<div className='search-results'> <div className='search-results'>
<div className='search-results__header'> <div className='search-results__header'>
<FormattedMessage id='search_results.total' defaultMessage='{count, number} {count, plural, one {result} other {results}}' values={{ count }} /> <FormattedMessage id='search_results.total' defaultMessage='{count} {count, plural, one {result} other {results}}' values={{ count }} />
</div> </div>
{accounts} {accounts}

View File

@@ -100,7 +100,7 @@ const en = {
"report.placeholder": "Additional comments", "report.placeholder": "Additional comments",
"report.submit": "Submit", "report.submit": "Submit",
"report.target": "Reporting", "report.target": "Reporting",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}", "search_results.total": "{count} {count, plural, one {result} other {results}}",
"search.placeholder": "Search", "search.placeholder": "Search",
"search.status_by": "Status by {name}", "search.status_by": "Status by {name}",
"status.delete": "Delete", "status.delete": "Delete",

View File

@@ -81,7 +81,7 @@ const fr = {
"search.placeholder": "Rechercher", "search.placeholder": "Rechercher",
"search.account": "Compte", "search.account": "Compte",
"search.hashtag": "Mot-clé", "search.hashtag": "Mot-clé",
"search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}", "search_results.total": "{count} {count, plural, one {résultat} other {résultats}}",
"search.status_by": "Statuts de {name}", "search.status_by": "Statuts de {name}",
"upload_button.label": "Joindre un média", "upload_button.label": "Joindre un média",
"upload_form.undo": "Annuler", "upload_form.undo": "Annuler",

View File

@@ -90,7 +90,7 @@ const hr = {
"report.placeholder": "Dodatni komentari", "report.placeholder": "Dodatni komentari",
"report.submit": "Pošalji", "report.submit": "Pošalji",
"report.target": "Prijavljivanje", "report.target": "Prijavljivanje",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}", "search_results.total": "{count} {count, plural, one {result} other {results}}",
"search.placeholder": "Traži", "search.placeholder": "Traži",
"search.status_by": "Status od {name}", "search.status_by": "Status od {name}",
"status.delete": "Obriši", "status.delete": "Obriši",

View File

@@ -18,7 +18,7 @@ const hu = {
"account.block": "Blokkolás", "account.block": "Blokkolás",
"account.follow": "Követés", "account.follow": "Követés",
"account.posts": "Posts", "account.posts": "Posts",
"account.follows": "Követve", "account.follows": "Követők",
"account.followers": "Követők", "account.followers": "Követők",
"account.follows_you": "Követnek téged", "account.follows_you": "Követnek téged",
"getting_started.heading": "Első lépések", "getting_started.heading": "Első lépések",

View File

@@ -3,7 +3,6 @@ import de from './de';
import es from './es'; import es from './es';
import hr from './hr'; import hr from './hr';
import hu from './hu'; import hu from './hu';
import it from './it';
import fr from './fr'; import fr from './fr';
import nl from './nl'; import nl from './nl';
import no from './no'; import no from './no';
@@ -24,7 +23,6 @@ const locales = {
es, es,
hr, hr,
hu, hu,
it,
fr, fr,
nl, nl,
no, no,

View File

@@ -1,125 +0,0 @@
const it = {
"account.block": "Blocca @{name}",
"account.disclaimer": "Questo utente si trova su un altro server. Questo numero potrebbe essere maggiore.",
"account.edit_profile": "Modifica profilo",
"account.follow": "Segui",
"account.followers": "Seguaci",
"account.follows_you": "Ti segue",
"account.follows": "Segue",
"account.mention": "Menziona @{name}",
"account.mute": "Silenzia @{name}",
"account.posts": "Posts",
"account.report": "Segnala @{name}",
"account.requested": "In attesa di approvazione",
"account.unblock": "Sblocca @{name}",
"account.unfollow": "Non seguire",
"account.unmute": "Non silenziare @{name}",
"boost_modal.combo": "Puoi premere {combo} per saltare questo passaggio la prossima volta",
"column_back_button.label": "Indietro",
"column.blocks": "Utenti bloccati",
"column.community": "Timeline locale",
"column.favourites": "Apprezzati",
"column.follow_requests": "Richieste di amicizia",
"column.home": "Home",
"column.mutes": "Utenti silenziati",
"column.notifications": "Notifiche",
"column.public": "Timeline federata",
"compose_form.placeholder": "A cosa stai pensando?",
"compose_form.privacy_disclaimer": "Il tuo status privato verrà condiviso con gli utenti menzionati su {domains}. Ti fidi di {domainsCount, plural, one {quel server} other {quei server}}? Le impostazioni sulla privacy valgono solo su server Mastodon. Se {domains} {domainsCount, plural, one {non è un server Mastodon} other {non sono server Mastodon}}, non ci saranno indicazioni sulla privacy del tuo status, e potrebbe essere condiviso o reso visibile a destinatari indesiderati.",
"compose_form.publish": "Toot",
"compose_form.sensitive": "Segnala file come sensibile",
"compose_form.spoiler_placeholder": "Content warning",
"compose_form.spoiler": "Nascondi testo con avvertimento",
"emoji_button.label": "Inserisci emoji",
"empty_column.community": "La timeline locale è vuota. Condividi qualcosa pubblicamente per dare inizio alla festa!",
"empty_column.hashtag": "Non c'è ancora nessun post con questo hashtag.",
"empty_column.home.public_timeline": "la timeline pubblica",
"empty_column.home": "Non stai ancora seguendo nessuno. Visita {public} o usa la ricerca per incontrare nuove persone.",
"empty_column.notifications": "Non hai ancora nessuna notifica. Interagisci con altri per iniziare conversazioni.",
"empty_column.public": "Qui non c'è nulla! Scrivi qualcosa pubblicamente, o aggiungi utenti da altri server per riempire questo spazio.",
"follow_request.authorize": "Autorizza",
"follow_request.reject": "Rifiuta",
"getting_started.apps": "Sono disponibili diverse app",
"getting_started.heading": "Come iniziare",
"getting_started.open_source_notice": "Mastodon è un software open source. Puoi contribuire o segnalare errori su GitHub all'indirizzo {github}. {apps}.",
"home.column_settings.advanced": "Avanzato",
"home.column_settings.basic": "Semplice",
"home.column_settings.filter_regex": "Filtra con espressioni regolari",
"home.column_settings.show_reblogs": "Mostra post condivisi",
"home.column_settings.show_replies": "Mostra risposte",
"home.settings": "Impostazioni colonna",
"lightbox.close": "Chiudi",
"loading_indicator.label": "Carico...",
"media_gallery.toggle_visible": "Imposta visibilità",
"missing_indicator.label": "Non trovato",
"navigation_bar.blocks": "Utenti bloccati",
"navigation_bar.community_timeline": "Timeline locale",
"navigation_bar.edit_profile": "Modifica profilo",
"navigation_bar.favourites": "Apprezzati",
"navigation_bar.follow_requests": "Richieste di amicizia",
"navigation_bar.info": "Informazioni estese",
"navigation_bar.logout": "Logout",
"navigation_bar.mutes": "Utenti silenziati",
"navigation_bar.preferences": "Impostazioni",
"navigation_bar.public_timeline": "Timeline federata",
"notification.favourite": "{name} ha apprezzato il tuo post",
"notification.follow": "{name} ha iniziato a seguirti",
"notification.mention": "{name} ti ha menzionato",
"notification.reblog": "{name} ha condiviso il tuo post",
"notifications.clear_confirmation": "Vuoi davvero cancellare tutte le notifiche?",
"notifications.clear": "Cancella notifiche",
"notifications.column_settings.alert": "Notifiche desktop",
"notifications.column_settings.favourite": "Apprezzati:",
"notifications.column_settings.follow": "Nuovi seguaci:",
"notifications.column_settings.mention": "Menzioni:",
"notifications.column_settings.reblog": "Post condivisi:",
"notifications.column_settings.show": "Mostra in colonna",
"notifications.column_settings.sound": "Riproduci suono",
"notifications.settings": "Impostazioni colonna",
"privacy.change": "Modifica privacy post",
"privacy.direct.long": "Invia solo a utenti menzionati",
"privacy.direct.short": "Diretto",
"privacy.private.long": "Invia solo ai seguaci",
"privacy.private.short": "Privato",
"privacy.public.long": "Invia alla timeline pubblica",
"privacy.public.short": "Pubblico",
"privacy.unlisted.long": "Non mostrare sulla timeline pubblica",
"privacy.unlisted.short": "Non elencato",
"reply_indicator.cancel": "Annulla",
"report.heading": "Nuova segnalazione",
"report.placeholder": "Commenti aggiuntivi",
"report.submit": "Invia",
"report.target": "Invio la segnalazione",
"search_results.total": "{count} {count, plural, one {risultato} other {risultati}}",
"search.placeholder": "Cerca",
"search.status_by": "Status per {name}",
"status.delete": "Elimina",
"status.favourite": "Apprezzato",
"status.load_more": "Mostra di più",
"status.media_hidden": "Allegato nascosto",
"status.mention": "Nomina @{name}",
"status.open": "Espandi questo post",
"status.reblog": "Condividi",
"status.reblogged_by": "{name} ha condiviso",
"status.reply": "Rispondi",
"status.report": "Segnala @{name}",
"status.sensitive_toggle": "Clicca per vedere",
"status.sensitive_warning": "Materiale sensibile",
"status.show_less": "Mostra meno",
"status.show_more": "Mostra di più",
"tabs_bar.compose": "Scrivi",
"tabs_bar.federated_timeline": "Federazione",
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Locale",
"tabs_bar.notifications": "Notifiche",
"upload_area.title": "Trascina per caricare",
"upload_button.label": "Aggiungi file multimediale",
"upload_form.undo": "Annulla",
"upload_progress.label": "Sto caricando...",
"video_player.toggle_sound": "Attiva suono",
"video_player.toggle_visible": "Attiva visibilità",
"video_player.expand": "Espandi video",
"video_player.video_error": "Il video non può essere riprodotto",
};
export default it;

View File

@@ -110,7 +110,7 @@ const ja = {
"report.target": "問題のユーザー", "report.target": "問題のユーザー",
"search.placeholder": "検索", "search.placeholder": "検索",
"search.status_by": "{name}からの投稿", "search.status_by": "{name}からの投稿",
"search_results.total": "{count, number} 件の結果", "search_results.total": "{count} 件",
"status.delete": "削除", "status.delete": "削除",
"status.favourite": "お気に入り", "status.favourite": "お気に入り",
"status.load_more": "もっと見る", "status.load_more": "もっと見る",

View File

@@ -59,7 +59,7 @@ const nl = {
"search.placeholder": "Zoeken", "search.placeholder": "Zoeken",
"search.account": "Account", "search.account": "Account",
"search.hashtag": "Hashtag", "search.hashtag": "Hashtag",
"search_results.total": "{count, number} {count, plural, one {resultaat} other {resultaten}}", "search_results.total": "{count} {count, plural, one {resultaat} other {resultaten}}",
"upload_button.label": "Media toevoegen", "upload_button.label": "Media toevoegen",
"upload_form.undo": "Ongedaan maken", "upload_form.undo": "Ongedaan maken",
"notification.follow": "{name} volgt jou nu", "notification.follow": "{name} volgt jou nu",

View File

@@ -87,7 +87,7 @@ const no = {
"report.placeholder": "Tilleggskommentarer", "report.placeholder": "Tilleggskommentarer",
"report.submit": "Send inn", "report.submit": "Send inn",
"report.target": "Rapporterer", "report.target": "Rapporterer",
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultater}}", "search_results.total": "{count} {count, plural, one {resultat} other {resultater}}",
"search.placeholder": "Søk", "search.placeholder": "Søk",
"search.status_by": "Status fra {name}", "search.status_by": "Status fra {name}",
"status.delete": "Slett", "status.delete": "Slett",

View File

@@ -80,7 +80,7 @@ const oc = {
"search.placeholder": "Recercar", "search.placeholder": "Recercar",
"search.account": "Compte", "search.account": "Compte",
"search.hashtag": "Mot-clau", "search.hashtag": "Mot-clau",
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}", "search_results.total": "{count} {count, plural, one {resultat} other {resultats}}",
"search.status_by": "Estatuts de {name}", "search.status_by": "Estatuts de {name}",
"upload_button.label": "Apondre un mèdia", "upload_button.label": "Apondre un mèdia",
"upload_form.undo": "Anullar", "upload_form.undo": "Anullar",

View File

@@ -90,7 +90,7 @@ const pt_br = {
"report.placeholder": "Comentários adicionais", "report.placeholder": "Comentários adicionais",
"report.submit": "Enviar", "report.submit": "Enviar",
"report.target": "Denunciar", "report.target": "Denunciar",
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "search_results.total": "{count} {count, plural, one {resultado} other {resultados}}",
"search.placeholder": "Pesquisar", "search.placeholder": "Pesquisar",
"search.status_by": "Post de {name}", "search.status_by": "Post de {name}",
"status.delete": "Eliminar", "status.delete": "Eliminar",

View File

@@ -90,7 +90,7 @@ const pt = {
"report.placeholder": "Comentários adicionais", "report.placeholder": "Comentários adicionais",
"report.submit": "Enviar", "report.submit": "Enviar",
"report.target": "Denunciar", "report.target": "Denunciar",
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "search_results.total": "{count} {count, plural, one {resultado} other {resultados}}",
"search.placeholder": "Pesquisar", "search.placeholder": "Pesquisar",
"search.status_by": "Post de {name}", "search.status_by": "Post de {name}",
"status.delete": "Eliminar", "status.delete": "Eliminar",

View File

@@ -92,7 +92,7 @@ const ru = {
"report.target": "Жалуемся на", "report.target": "Жалуемся на",
"search.placeholder": "Поиск", "search.placeholder": "Поиск",
"search.status_by": "Статус от {name}", "search.status_by": "Статус от {name}",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}", "search_results.total": "{count} {count, plural, one {result} other {results}}",
"status.delete": "Удалить", "status.delete": "Удалить",
"status.favourite": "Нравится", "status.favourite": "Нравится",
"status.load_more": "Показать еще", "status.load_more": "Показать еще",

View File

@@ -119,7 +119,7 @@ const zh_cn = {
"report.placeholder": "额外消息", "report.placeholder": "额外消息",
"report.submit": "提交", "report.submit": "提交",
"report.target": "Reporting", "report.target": "Reporting",
"search_results.total": "{count, number} 项结果", "search_results.total": "{count} 项结果",
"search.account": "用户", "search.account": "用户",
"search.hashtag": "标签", "search.hashtag": "标签",
"search.placeholder": "搜索", "search.placeholder": "搜索",

View File

@@ -112,7 +112,7 @@ const zh_hk = {
"report.placeholder": "額外訊息", "report.placeholder": "額外訊息",
"report.submit": "提交", "report.submit": "提交",
"report.target": "Reporting", "report.target": "Reporting",
"search_results.total": "{count, number} 項結果", "search_results.total": "{count} 項結果",
"search.account": "用戶", "search.account": "用戶",
"search.hashtag": "標籤", "search.hashtag": "標籤",
"search.placeholder": "搜尋", "search.placeholder": "搜尋",

View File

@@ -237,14 +237,13 @@
} }
.accounts-grid { .accounts-grid {
clear: both;
box-shadow: 0 0 15px rgba($color8, 0.2); box-shadow: 0 0 15px rgba($color8, 0.2);
background: $color5; background: $color5;
border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px;
padding: 20px 10px; padding: 20px 10px;
padding-bottom: 10px; padding-bottom: 10px;
overflow: hidden; overflow: hidden;
display: flex;
flex-wrap: wrap;
@media screen and (max-width: 700px) { @media screen and (max-width: 700px) {
border-radius: 0; border-radius: 0;
@@ -254,9 +253,11 @@
.account-grid-card { .account-grid-card {
box-sizing: border-box; box-sizing: border-box;
width: 335px; width: 335px;
float: left;
border: 1px solid $color2; border: 1px solid $color2;
border-radius: 4px; border-radius: 4px;
color: $color1; color: $color1;
height: 160px;
margin-bottom: 10px; margin-bottom: 10px;
&:nth-child(odd) { &:nth-child(odd) {

View File

@@ -135,6 +135,10 @@ class Account < ApplicationRecord
!subscription_expires_at.blank? !subscription_expires_at.blank?
end end
def followers_domains
followers.reorder(nil).pluck('distinct accounts.domain')
end
def favourited?(status) def favourited?(status)
status.proper.favourites.where(account: self).count.positive? status.proper.favourites.where(account: self).count.positive?
end end

View File

@@ -10,7 +10,7 @@ class FollowRemoteAccountService < BaseService
# important information from their feed # important information from their feed
# @param [String] uri User URI in the form of username@domain # @param [String] uri User URI in the form of username@domain
# @return [Account] # @return [Account]
def call(uri, redirected = nil) def call(uri)
username, domain = uri.split('@') username, domain = uri.split('@')
return Account.find_local(username) if TagManager.instance.local_domain?(domain) return Account.find_local(username) if TagManager.instance.local_domain?(domain)
@@ -24,14 +24,8 @@ class FollowRemoteAccountService < BaseService
raise Goldfinger::Error, 'Missing resource links' if data.link('http://schemas.google.com/g/2010#updates-from').nil? || data.link('salmon').nil? || data.link('http://webfinger.net/rel/profile-page').nil? || data.link('magic-public-key').nil? raise Goldfinger::Error, 'Missing resource links' if data.link('http://schemas.google.com/g/2010#updates-from').nil? || data.link('salmon').nil? || data.link('http://webfinger.net/rel/profile-page').nil? || data.link('magic-public-key').nil?
# Disallow account hijacking
confirmed_username, confirmed_domain = data.subject.gsub(/\Aacct:/, '').split('@') confirmed_username, confirmed_domain = data.subject.gsub(/\Aacct:/, '').split('@')
unless confirmed_username.casecmp(username).zero? && confirmed_domain.casecmp(domain).zero?
return call("#{confirmed_username}@#{confirmed_domain}", true) if redirected.nil?
raise Goldfinger::Error, 'Requested and returned acct URI do not match'
end
return Account.find_local(confirmed_username) if TagManager.instance.local_domain?(confirmed_domain) return Account.find_local(confirmed_username) if TagManager.instance.local_domain?(confirmed_domain)
confirmed_account = Account.find_remote(confirmed_username, confirmed_domain) confirmed_account = Account.find_remote(confirmed_username, confirmed_domain)

View File

@@ -1,7 +0,0 @@
%meta{ property: 'og:site_name', content: site_title }/
%meta{ property: 'og:title', content: [yield(:page_title).strip.presence, site_title].compact.join(' - ') }/
%meta{ property: 'og:description', content: account.note }/
%meta{ property: 'og:image', content: full_asset_url(account.avatar.url(:original)) }/
%meta{ property: 'og:image:width', content: '120' }/
%meta{ property: 'og:image:height', content: '120' }/
%meta{ property: 'twitter:card', content: 'summary' }/

View File

@@ -0,0 +1,12 @@
- content_for :page_title do
= t('accounts.people_who_follow', name: display_name(@account))
= render 'header', account: @account
.accounts-grid
- if @followers.empty?
= render 'nothing_here'
- else
= render partial: 'grid_card', collection: @followers, as: :account, cached: true
= paginate @followers

View File

@@ -0,0 +1,12 @@
- content_for :page_title do
= t('accounts.people_followed_by', name: display_name(@account))
= render 'header', account: @account
.accounts-grid
- if @following.empty?
= render 'nothing_here'
- else
= render partial: 'grid_card', collection: @following, as: :account, cached: true
= paginate @following

View File

@@ -5,8 +5,14 @@
%link{ rel: 'salmon', href: api_salmon_url(@account.id) }/ %link{ rel: 'salmon', href: api_salmon_url(@account.id) }/
%link{ rel: 'alternate', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }/ %link{ rel: 'alternate', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }/
%meta{ property: 'og:site_name', content: site_title }/
%meta{ property: 'og:type', content: 'profile' }/ %meta{ property: 'og:type', content: 'profile' }/
= render 'og', account: @account %meta{ property: 'og:title', content: "#{@account.username} on #{site_hostname}" }/
%meta{ property: 'og:description', content: @account.note }/
%meta{ property: 'og:image', content: full_asset_url(@account.avatar.url(:original)) }/
%meta{ property: 'og:image:width', content: '120' }/
%meta{ property: 'og:image:height', content: '120' }/
%meta{ property: 'twitter:card', content: 'summary' }/
- if show_landing_strip? - if show_landing_strip?
= render partial: 'shared/landing_strip', locals: { account: @account } = render partial: 'shared/landing_strip', locals: { account: @account }

View File

@@ -1,9 +1,6 @@
- content_for :page_title do - content_for :page_title do
= t('accounts.people_who_follow', name: display_name(@account)) = t('accounts.people_who_follow', name: display_name(@account))
- content_for :header_tags do
= render 'accounts/og', account: @account
= render 'accounts/header', account: @account = render 'accounts/header', account: @account
= render 'accounts/follow_grid', accounts: @accounts = render 'accounts/follow_grid', accounts: @accounts

View File

@@ -1,9 +1,6 @@
- content_for :page_title do - content_for :page_title do
= t('accounts.people_followed_by', name: display_name(@account)) = t('accounts.people_followed_by', name: display_name(@account))
- content_for :header_tags do
= render 'accounts/og', account: @account
= render 'accounts/header', account: @account = render 'accounts/header', account: @account
= render 'accounts/follow_grid', accounts: @accounts = render 'accounts/follow_grid', accounts: @accounts

View File

@@ -14,7 +14,7 @@
%title< %title<
- if content_for?(:page_title) - if content_for?(:page_title)
= yield(:page_title) = yield(:page_title).strip
= ' - ' = ' - '
= site_title = site_title

View File

@@ -8,12 +8,14 @@ class Pubsubhubbub::DistributionWorker
def perform(stream_entry_id) def perform(stream_entry_id)
stream_entry = StreamEntry.find(stream_entry_id) stream_entry = StreamEntry.find(stream_entry_id)
return if stream_entry.hidden? return if stream_entry.status.direct_visibility?
account = stream_entry.account account = stream_entry.account
payload = AtomSerializer.render(AtomSerializer.new.feed(account, [stream_entry])) payload = AtomSerializer.render(AtomSerializer.new.feed(account, [stream_entry]))
domains = account.followers_domains
Subscription.where(account: account).active.select('id, callback_url').find_each do |subscription| Subscription.where(account: account).active.select('id, callback_url').find_each do |subscription|
next unless domains.include?(Addressable::URI.parse(subscription.callback_url).host)
Pubsubhubbub::DeliveryWorker.perform_async(subscription.id, payload) Pubsubhubbub::DeliveryWorker.perform_async(subscription.id, payload)
end end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound

View File

@@ -3,35 +3,10 @@ require 'rails_helper'
RSpec.describe FollowRemoteAccountService do RSpec.describe FollowRemoteAccountService do
subject { FollowRemoteAccountService.new } subject { FollowRemoteAccountService.new }
before do it 'returns nil if no such user can be resolved via webfinger'
stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt')) it 'returns nil if the domain does not have webfinger'
stub_request(:get, "https://example.com/.well-known/host-meta").to_return(status: 404) it 'returns nil if remote user does not offer a hub URL'
stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:gargron@quitter.no").to_return(request_fixture('webfinger.txt')) it 'returns an already existing remote account'
stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:catsrgr8@quitter.no").to_return(status: 404) it 'returns a new remote account'
stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt')) it 'fills the remote account with profile information'
stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
end
it 'raises error if no such user can be resolved via webfinger' do
expect { subject.call('catsrgr8@quitter.no') }.to raise_error Goldfinger::Error
end
it 'raises error if the domain does not have webfinger' do
expect { subject.call('catsrgr8@example.com') }.to raise_error Goldfinger::Error
end
it 'returns an already existing remote account' do
old_account = Fabricate(:account, username: 'gargron', domain: 'quitter.no')
returned_account = subject.call('gargron@quitter.no')
expect(old_account.id).to eq returned_account.id
end
it 'returns a new remote account' do
account = subject.call('gargron@quitter.no')
expect(account.username).to eq 'gargron'
expect(account.domain).to eq 'quitter.no'
expect(account.remote_url).to eq 'https://quitter.no/api/statuses/user_timeline/7477.atom'
end
end end