Per-status control for unlisted mode, also federation for unlisted mode
Fix #233, fix #268
This commit is contained in:
		
							
								
								
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
GIT
 | 
					GIT
 | 
				
			||||||
  remote: https://github.com/rails/rails.git
 | 
					  remote: https://github.com/rails/rails.git
 | 
				
			||||||
  revision: ecb394a31420f6fd1d0ab692c79f2dd44176e2c9
 | 
					  revision: c7a716aa5a692cae301d56b345faa5d79cbfc320
 | 
				
			||||||
  branch: 5-0-stable
 | 
					  branch: 5-0-stable
 | 
				
			||||||
  specs:
 | 
					  specs:
 | 
				
			||||||
    actioncable (5.0.0.1)
 | 
					    actioncable (5.0.0.1)
 | 
				
			||||||
@@ -110,7 +110,7 @@ GEM
 | 
				
			|||||||
    coffee-script-source (1.10.0)
 | 
					    coffee-script-source (1.10.0)
 | 
				
			||||||
    colorize (0.8.1)
 | 
					    colorize (0.8.1)
 | 
				
			||||||
    concurrent-ruby (1.0.2)
 | 
					    concurrent-ruby (1.0.2)
 | 
				
			||||||
    connection_pool (2.2.0)
 | 
					    connection_pool (2.2.1)
 | 
				
			||||||
    crack (0.4.3)
 | 
					    crack (0.4.3)
 | 
				
			||||||
      safe_yaml (~> 1.0.0)
 | 
					      safe_yaml (~> 1.0.0)
 | 
				
			||||||
    debug_inspector (0.0.2)
 | 
					    debug_inspector (0.0.2)
 | 
				
			||||||
@@ -287,7 +287,7 @@ GEM
 | 
				
			|||||||
      execjs
 | 
					      execjs
 | 
				
			||||||
      railties (>= 3.2)
 | 
					      railties (>= 3.2)
 | 
				
			||||||
      tilt
 | 
					      tilt
 | 
				
			||||||
    redis (3.3.1)
 | 
					    redis (3.3.2)
 | 
				
			||||||
    redis-actionpack (5.0.0)
 | 
					    redis-actionpack (5.0.0)
 | 
				
			||||||
      actionpack (>= 4.0.0, < 6)
 | 
					      actionpack (>= 4.0.0, < 6)
 | 
				
			||||||
      redis-rack (~> 2.0.0.pre)
 | 
					      redis-rack (~> 2.0.0.pre)
 | 
				
			||||||
@@ -348,10 +348,10 @@ GEM
 | 
				
			|||||||
    sdoc (0.4.1)
 | 
					    sdoc (0.4.1)
 | 
				
			||||||
      json (~> 1.7, >= 1.7.7)
 | 
					      json (~> 1.7, >= 1.7.7)
 | 
				
			||||||
      rdoc (~> 4.0)
 | 
					      rdoc (~> 4.0)
 | 
				
			||||||
    sidekiq (4.2.1)
 | 
					    sidekiq (4.2.7)
 | 
				
			||||||
      concurrent-ruby (~> 1.0)
 | 
					      concurrent-ruby (~> 1.0)
 | 
				
			||||||
      connection_pool (~> 2.2, >= 2.2.0)
 | 
					      connection_pool (~> 2.2, >= 2.2.0)
 | 
				
			||||||
      rack-protection (~> 1.5)
 | 
					      rack-protection (>= 1.5.0)
 | 
				
			||||||
      redis (~> 3.2, >= 3.2.1)
 | 
					      redis (~> 3.2, >= 3.2.1)
 | 
				
			||||||
    simple_form (3.2.1)
 | 
					    simple_form (3.2.1)
 | 
				
			||||||
      actionpack (> 4, < 5.1)
 | 
					      actionpack (> 4, < 5.1)
 | 
				
			||||||
@@ -374,7 +374,7 @@ GEM
 | 
				
			|||||||
      tins (~> 1.0)
 | 
					      tins (~> 1.0)
 | 
				
			||||||
    terminal-table (1.7.0)
 | 
					    terminal-table (1.7.0)
 | 
				
			||||||
      unicode-display_width (~> 1.1)
 | 
					      unicode-display_width (~> 1.1)
 | 
				
			||||||
    thor (0.19.1)
 | 
					    thor (0.19.4)
 | 
				
			||||||
    thread (0.2.2)
 | 
					    thread (0.2.2)
 | 
				
			||||||
    thread_safe (0.3.5)
 | 
					    thread_safe (0.3.5)
 | 
				
			||||||
    tilt (2.0.5)
 | 
					    tilt (2.0.5)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ export const COMPOSE_MOUNT   = 'COMPOSE_MOUNT';
 | 
				
			|||||||
export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
 | 
					export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
 | 
					export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
 | 
				
			||||||
 | 
					export const COMPOSE_VISIBILITY_CHANGE  = 'COMPOSE_VISIBILITY_CHANGE';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function changeCompose(text) {
 | 
					export function changeCompose(text) {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
@@ -65,7 +66,8 @@ export function submitCompose() {
 | 
				
			|||||||
      status: getState().getIn(['compose', 'text'], ''),
 | 
					      status: getState().getIn(['compose', 'text'], ''),
 | 
				
			||||||
      in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
 | 
					      in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
 | 
				
			||||||
      media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
 | 
					      media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
 | 
				
			||||||
      sensitive: getState().getIn(['compose', 'sensitive'])
 | 
					      sensitive: getState().getIn(['compose', 'sensitive']),
 | 
				
			||||||
 | 
					      unlisted: getState().getIn(['compose', 'unlisted'])
 | 
				
			||||||
    }).then(function (response) {
 | 
					    }).then(function (response) {
 | 
				
			||||||
      dispatch(submitComposeSuccess(response.data));
 | 
					      dispatch(submitComposeSuccess(response.data));
 | 
				
			||||||
      dispatch(updateTimeline('home', response.data));
 | 
					      dispatch(updateTimeline('home', response.data));
 | 
				
			||||||
@@ -207,3 +209,10 @@ export function changeComposeSensitivity(checked) {
 | 
				
			|||||||
    checked
 | 
					    checked
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function changeComposeVisibility(checked) {
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    type: COMPOSE_VISIBILITY_CHANGE,
 | 
				
			||||||
 | 
					    checked
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,7 @@ const ComposeForm = React.createClass({
 | 
				
			|||||||
    suggestion_token: React.PropTypes.string,
 | 
					    suggestion_token: React.PropTypes.string,
 | 
				
			||||||
    suggestions: React.PropTypes.array,
 | 
					    suggestions: React.PropTypes.array,
 | 
				
			||||||
    sensitive: React.PropTypes.bool,
 | 
					    sensitive: React.PropTypes.bool,
 | 
				
			||||||
 | 
					    unlisted: React.PropTypes.bool,
 | 
				
			||||||
    is_submitting: React.PropTypes.bool,
 | 
					    is_submitting: React.PropTypes.bool,
 | 
				
			||||||
    is_uploading: React.PropTypes.bool,
 | 
					    is_uploading: React.PropTypes.bool,
 | 
				
			||||||
    in_reply_to: ImmutablePropTypes.map,
 | 
					    in_reply_to: ImmutablePropTypes.map,
 | 
				
			||||||
@@ -79,7 +80,8 @@ const ComposeForm = React.createClass({
 | 
				
			|||||||
    onClearSuggestions: React.PropTypes.func.isRequired,
 | 
					    onClearSuggestions: React.PropTypes.func.isRequired,
 | 
				
			||||||
    onFetchSuggestions: React.PropTypes.func.isRequired,
 | 
					    onFetchSuggestions: React.PropTypes.func.isRequired,
 | 
				
			||||||
    onSuggestionSelected: React.PropTypes.func.isRequired,
 | 
					    onSuggestionSelected: React.PropTypes.func.isRequired,
 | 
				
			||||||
    onChangeSensitivity: React.PropTypes.func.isRequired
 | 
					    onChangeSensitivity: React.PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    onChangeVisibility: React.PropTypes.func.isRequired
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mixins: [PureRenderMixin],
 | 
					  mixins: [PureRenderMixin],
 | 
				
			||||||
@@ -147,6 +149,10 @@ const ComposeForm = React.createClass({
 | 
				
			|||||||
    this.props.onChangeSensitivity(e.target.checked);
 | 
					    this.props.onChangeSensitivity(e.target.checked);
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleChangeVisibility (e) {
 | 
				
			||||||
 | 
					    this.props.onChangeVisibility(e.target.checked);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { intl } = this.props;
 | 
					    const { intl } = this.props;
 | 
				
			||||||
    let replyArea  = '';
 | 
					    let replyArea  = '';
 | 
				
			||||||
@@ -187,7 +193,12 @@ const ComposeForm = React.createClass({
 | 
				
			|||||||
          <UploadButtonContainer style={{ paddingTop: '4px' }} />
 | 
					          <UploadButtonContainer style={{ paddingTop: '4px' }} />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <label style={{ display: 'block', lineHeight: '24px', verticalAlign: 'middle', marginTop: '10px', borderTop: '1px solid #616b86', paddingTop: '10px' }}>
 | 
					        <label style={{ display: 'block', lineHeight: '24px', verticalAlign: 'middle', marginTop: '10px', borderTop: '1px solid #282c37', paddingTop: '10px' }}>
 | 
				
			||||||
 | 
					          <Toggle checked={this.props.unlisted} onChange={this.handleChangeVisibility} />
 | 
				
			||||||
 | 
					          <span style={{ display: 'inline-block', verticalAlign: 'middle', marginBottom: '14px', marginLeft: '8px', color: '#9baec8' }}><FormattedMessage id='compose_form.unlisted' defaultMessage='Unlisted mode' /></span>
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <label style={{ display: 'block', lineHeight: '24px', verticalAlign: 'middle' }}>
 | 
				
			||||||
          <Toggle checked={this.props.sensitive} onChange={this.handleChangeSensitivity} />
 | 
					          <Toggle checked={this.props.sensitive} onChange={this.handleChangeSensitivity} />
 | 
				
			||||||
          <span style={{ display: 'inline-block', verticalAlign: 'middle', marginBottom: '14px', marginLeft: '8px', color: '#9baec8' }}><FormattedMessage id='compose_form.sensitive' defaultMessage='Mark content as sensitive' /></span>
 | 
					          <span style={{ display: 'inline-block', verticalAlign: 'middle', marginBottom: '14px', marginLeft: '8px', color: '#9baec8' }}><FormattedMessage id='compose_form.sensitive' defaultMessage='Mark content as sensitive' /></span>
 | 
				
			||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,8 @@ import {
 | 
				
			|||||||
  clearComposeSuggestions,
 | 
					  clearComposeSuggestions,
 | 
				
			||||||
  fetchComposeSuggestions,
 | 
					  fetchComposeSuggestions,
 | 
				
			||||||
  selectComposeSuggestion,
 | 
					  selectComposeSuggestion,
 | 
				
			||||||
  changeComposeSensitivity
 | 
					  changeComposeSensitivity,
 | 
				
			||||||
 | 
					  changeComposeVisibility
 | 
				
			||||||
} from '../../../actions/compose';
 | 
					} from '../../../actions/compose';
 | 
				
			||||||
import { makeGetStatus } from '../../../selectors';
 | 
					import { makeGetStatus } from '../../../selectors';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,6 +21,7 @@ const makeMapStateToProps = () => {
 | 
				
			|||||||
      suggestion_token: state.getIn(['compose', 'suggestion_token']),
 | 
					      suggestion_token: state.getIn(['compose', 'suggestion_token']),
 | 
				
			||||||
      suggestions: state.getIn(['compose', 'suggestions']).toJS(),
 | 
					      suggestions: state.getIn(['compose', 'suggestions']).toJS(),
 | 
				
			||||||
      sensitive: state.getIn(['compose', 'sensitive']),
 | 
					      sensitive: state.getIn(['compose', 'sensitive']),
 | 
				
			||||||
 | 
					      unlisted: state.getIn(['compose', 'unlisted']),
 | 
				
			||||||
      is_submitting: state.getIn(['compose', 'is_submitting']),
 | 
					      is_submitting: state.getIn(['compose', 'is_submitting']),
 | 
				
			||||||
      is_uploading: state.getIn(['compose', 'is_uploading']),
 | 
					      is_uploading: state.getIn(['compose', 'is_uploading']),
 | 
				
			||||||
      in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to']))
 | 
					      in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to']))
 | 
				
			||||||
@@ -57,6 +59,10 @@ const mapDispatchToProps = function (dispatch) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    onChangeSensitivity (checked) {
 | 
					    onChangeSensitivity (checked) {
 | 
				
			||||||
      dispatch(changeComposeSensitivity(checked));
 | 
					      dispatch(changeComposeSensitivity(checked));
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onChangeVisibility (checked) {
 | 
				
			||||||
 | 
					      dispatch(changeComposeVisibility(checked));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,8 @@ const en = {
 | 
				
			|||||||
  "tabs_bar.notifications": "Mitteilungen",
 | 
					  "tabs_bar.notifications": "Mitteilungen",
 | 
				
			||||||
  "compose_form.placeholder": "Worüber möchstest du schreiben?",
 | 
					  "compose_form.placeholder": "Worüber möchstest du schreiben?",
 | 
				
			||||||
  "compose_form.publish": "Veröffentlichen",
 | 
					  "compose_form.publish": "Veröffentlichen",
 | 
				
			||||||
 | 
					  "compose_form.sensitive": "Medien als sensitiv markieren",
 | 
				
			||||||
 | 
					  "compose_form.unlisted": "Öffentlich nicht auflisten",
 | 
				
			||||||
  "navigation_bar.settings": "Einstellungen",
 | 
					  "navigation_bar.settings": "Einstellungen",
 | 
				
			||||||
  "navigation_bar.public_timeline": "Öffentlich",
 | 
					  "navigation_bar.public_timeline": "Öffentlich",
 | 
				
			||||||
  "navigation_bar.logout": "Abmelden",
 | 
					  "navigation_bar.logout": "Abmelden",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,7 @@ const en = {
 | 
				
			|||||||
  "compose_form.placeholder": "What is on your mind?",
 | 
					  "compose_form.placeholder": "What is on your mind?",
 | 
				
			||||||
  "compose_form.publish": "Toot",
 | 
					  "compose_form.publish": "Toot",
 | 
				
			||||||
  "compose_form.sensitive": "Mark content as sensitive",
 | 
					  "compose_form.sensitive": "Mark content as sensitive",
 | 
				
			||||||
 | 
					  "compose_form.unlisted": "Unlisted mode",
 | 
				
			||||||
  "navigation_bar.settings": "Settings",
 | 
					  "navigation_bar.settings": "Settings",
 | 
				
			||||||
  "navigation_bar.public_timeline": "Public timeline",
 | 
					  "navigation_bar.public_timeline": "Public timeline",
 | 
				
			||||||
  "navigation_bar.logout": "Logout",
 | 
					  "navigation_bar.logout": "Logout",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,8 @@ const es = {
 | 
				
			|||||||
  "tabs_bar.notifications": "Notificaciones",
 | 
					  "tabs_bar.notifications": "Notificaciones",
 | 
				
			||||||
  "compose_form.placeholder": "¿En qué estás pensando?",
 | 
					  "compose_form.placeholder": "¿En qué estás pensando?",
 | 
				
			||||||
  "compose_form.publish": "Publicar",
 | 
					  "compose_form.publish": "Publicar",
 | 
				
			||||||
 | 
					  "compose_form.sensitive": null,
 | 
				
			||||||
 | 
					  "compose_form.unlisted": "No listado",
 | 
				
			||||||
  "navigation_bar.settings": "Ajustes",
 | 
					  "navigation_bar.settings": "Ajustes",
 | 
				
			||||||
  "navigation_bar.public_timeline": "Público",
 | 
					  "navigation_bar.public_timeline": "Público",
 | 
				
			||||||
  "navigation_bar.logout": "Cerrar sesión",
 | 
					  "navigation_bar.logout": "Cerrar sesión",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,8 @@ const fr = {
 | 
				
			|||||||
  "tabs_bar.notifications": "Notifications",
 | 
					  "tabs_bar.notifications": "Notifications",
 | 
				
			||||||
  "compose_form.placeholder": "Qu’avez-vous en tête ?",
 | 
					  "compose_form.placeholder": "Qu’avez-vous en tête ?",
 | 
				
			||||||
  "compose_form.publish": "Pouet",
 | 
					  "compose_form.publish": "Pouet",
 | 
				
			||||||
  "compose_form.sensitive": "Marquer le contenu comme délicat", 
 | 
					  "compose_form.sensitive": "Marquer le contenu comme délicat",
 | 
				
			||||||
 | 
					  "compose_form.unlisted": "Ne pas apparaître dans le fil public",
 | 
				
			||||||
  "navigation_bar.settings": "Paramètres",
 | 
					  "navigation_bar.settings": "Paramètres",
 | 
				
			||||||
  "navigation_bar.public_timeline": "Public",
 | 
					  "navigation_bar.public_timeline": "Public",
 | 
				
			||||||
  "navigation_bar.logout": "Déconnexion",
 | 
					  "navigation_bar.logout": "Déconnexion",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,7 @@ const hu = {
 | 
				
			|||||||
  "compose_form.placeholder": "Mire gondolsz?",
 | 
					  "compose_form.placeholder": "Mire gondolsz?",
 | 
				
			||||||
  "compose_form.publish": "Tülk!",
 | 
					  "compose_form.publish": "Tülk!",
 | 
				
			||||||
  "compose_form.sensitive": "Tartalom érzékenynek jelölése",
 | 
					  "compose_form.sensitive": "Tartalom érzékenynek jelölése",
 | 
				
			||||||
 | 
					  "compose_form.unlisted": "Listázatlan mód",
 | 
				
			||||||
  "navigation_bar.settings": "Beállítások",
 | 
					  "navigation_bar.settings": "Beállítások",
 | 
				
			||||||
  "navigation_bar.public_timeline": "Nyilvános időfolyam",
 | 
					  "navigation_bar.public_timeline": "Nyilvános időfolyam",
 | 
				
			||||||
  "navigation_bar.logout": "Kijelentkezés",
 | 
					  "navigation_bar.logout": "Kijelentkezés",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,8 @@ const pt = {
 | 
				
			|||||||
  "tabs_bar.public": "Público",
 | 
					  "tabs_bar.public": "Público",
 | 
				
			||||||
  "compose_form.placeholder": "Que estás pensando?",
 | 
					  "compose_form.placeholder": "Que estás pensando?",
 | 
				
			||||||
  "compose_form.publish": "Publicar",
 | 
					  "compose_form.publish": "Publicar",
 | 
				
			||||||
 | 
					  "compose_form.sensitive": null,
 | 
				
			||||||
 | 
					  "compose_form.unlisted": null,
 | 
				
			||||||
  "navigation_bar.settings": "Configurações",
 | 
					  "navigation_bar.settings": "Configurações",
 | 
				
			||||||
  "navigation_bar.public_timeline": "Timeline Pública",
 | 
					  "navigation_bar.public_timeline": "Timeline Pública",
 | 
				
			||||||
  "navigation_bar.logout": "Logout",
 | 
					  "navigation_bar.logout": "Logout",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,8 @@ import {
 | 
				
			|||||||
  COMPOSE_SUGGESTIONS_CLEAR,
 | 
					  COMPOSE_SUGGESTIONS_CLEAR,
 | 
				
			||||||
  COMPOSE_SUGGESTIONS_READY,
 | 
					  COMPOSE_SUGGESTIONS_READY,
 | 
				
			||||||
  COMPOSE_SUGGESTION_SELECT,
 | 
					  COMPOSE_SUGGESTION_SELECT,
 | 
				
			||||||
  COMPOSE_SENSITIVITY_CHANGE
 | 
					  COMPOSE_SENSITIVITY_CHANGE,
 | 
				
			||||||
 | 
					  COMPOSE_VISIBILITY_CHANGE
 | 
				
			||||||
} from '../actions/compose';
 | 
					} from '../actions/compose';
 | 
				
			||||||
import { TIMELINE_DELETE } from '../actions/timelines';
 | 
					import { TIMELINE_DELETE } from '../actions/timelines';
 | 
				
			||||||
import { ACCOUNT_SET_SELF } from '../actions/accounts';
 | 
					import { ACCOUNT_SET_SELF } from '../actions/accounts';
 | 
				
			||||||
@@ -25,6 +26,7 @@ import Immutable from 'immutable';
 | 
				
			|||||||
const initialState = Immutable.Map({
 | 
					const initialState = Immutable.Map({
 | 
				
			||||||
  mounted: false,
 | 
					  mounted: false,
 | 
				
			||||||
  sensitive: false,
 | 
					  sensitive: false,
 | 
				
			||||||
 | 
					  unlisted: false,
 | 
				
			||||||
  text: '',
 | 
					  text: '',
 | 
				
			||||||
  in_reply_to: null,
 | 
					  in_reply_to: null,
 | 
				
			||||||
  is_submitting: false,
 | 
					  is_submitting: false,
 | 
				
			||||||
@@ -91,6 +93,8 @@ export default function compose(state = initialState, action) {
 | 
				
			|||||||
      return state.set('mounted', false);
 | 
					      return state.set('mounted', false);
 | 
				
			||||||
    case COMPOSE_SENSITIVITY_CHANGE:
 | 
					    case COMPOSE_SENSITIVITY_CHANGE:
 | 
				
			||||||
      return state.set('sensitive', action.checked);
 | 
					      return state.set('sensitive', action.checked);
 | 
				
			||||||
 | 
					    case COMPOSE_VISIBILITY_CHANGE:
 | 
				
			||||||
 | 
					      return state.set('unlisted', action.checked);
 | 
				
			||||||
    case COMPOSE_CHANGE:
 | 
					    case COMPOSE_CHANGE:
 | 
				
			||||||
      return state.set('text', action.text);
 | 
					      return state.set('text', action.text);
 | 
				
			||||||
    case COMPOSE_REPLY:
 | 
					    case COMPOSE_REPLY:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,7 @@ class Api::V1::StatusesController < ApiController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create
 | 
					  def create
 | 
				
			||||||
    @status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), media_ids: params[:media_ids], sensitive: params[:sensitive])
 | 
					    @status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), media_ids: params[:media_ids], sensitive: params[:sensitive], unlisted: params[:unlisted])
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,7 +73,7 @@ class Api::V1::StatusesController < ApiController
 | 
				
			|||||||
    @reblogged_map = { @status.id => false }
 | 
					    @reblogged_map = { @status.id => false }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RemovalWorker.perform_async(reblog.id)
 | 
					    RemovalWorker.perform_async(reblog.id)
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    render action: :show
 | 
					    render action: :show
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
module ObfuscateFilename
 | 
					module ObfuscateFilename
 | 
				
			||||||
  extend ActiveSupport::Concern
 | 
					  extend ActiveSupport::Concern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,6 +12,6 @@ module ObfuscateFilename
 | 
				
			|||||||
    file = params.dig(*path)
 | 
					    file = params.dig(*path)
 | 
				
			||||||
    return if file.nil?
 | 
					    return if file.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    file.original_filename = "media" + File.extname(file.original_filename)
 | 
					    file.original_filename = 'media' + File.extname(file.original_filename)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
@@ -24,7 +24,7 @@ class Settings::ProfilesController < ApplicationController
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def account_params
 | 
					  def account_params
 | 
				
			||||||
    params.require(:account).permit(:display_name, :note, :avatar, :header, :silenced)
 | 
					    params.require(:account).permit(:display_name, :note, :avatar, :header)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def set_account
 | 
					  def set_account
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@ module AtomBuilderHelper
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def verb(xml, verb)
 | 
					  def verb(xml, verb)
 | 
				
			||||||
    xml['activity'].send('verb', "http://activitystrea.ms/schema/1.0/#{verb}")
 | 
					    xml['activity'].send('verb', TagManager::VERBS[verb])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def content(xml, content)
 | 
					  def content(xml, content)
 | 
				
			||||||
@@ -62,7 +62,7 @@ module AtomBuilderHelper
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def object_type(xml, type)
 | 
					  def object_type(xml, type)
 | 
				
			||||||
    xml['activity'].send('object-type', "http://activitystrea.ms/schema/1.0/#{type}")
 | 
					    xml['activity'].send('object-type', TagManager::TYPES[type])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def uri(xml, uri)
 | 
					  def uri(xml, uri)
 | 
				
			||||||
@@ -108,7 +108,7 @@ module AtomBuilderHelper
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def link_mention(xml, account)
 | 
					  def link_mention(xml, account)
 | 
				
			||||||
    xml.link(rel: 'mentioned', href: TagManager.instance.uri_for(account))
 | 
					    xml.link(:rel => 'mentioned', :href => TagManager.instance.uri_for(account), 'ostatus:object-type' => TagManager::TYPES[:person])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def link_enclosure(xml, media)
 | 
					  def link_enclosure(xml, media)
 | 
				
			||||||
@@ -139,6 +139,11 @@ module AtomBuilderHelper
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def link_visibility(xml, item)
 | 
				
			||||||
 | 
					    return unless item.respond_to?(:visibility) && item.public_visibility?
 | 
				
			||||||
 | 
					    xml.link(:rel => 'mentioned', :href => TagManager::COLLECTIONS[:public], 'ostatus:object-type' => TagManager::TYPES[:collection])
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def include_author(xml, account)
 | 
					  def include_author(xml, account)
 | 
				
			||||||
    object_type      xml, :person
 | 
					    object_type      xml, :person
 | 
				
			||||||
    uri              xml, TagManager.instance.uri_for(account)
 | 
					    uri              xml, TagManager.instance.uri_for(account)
 | 
				
			||||||
@@ -189,6 +194,8 @@ module AtomBuilderHelper
 | 
				
			|||||||
            include_author xml, stream_entry.target.account
 | 
					            include_author xml, stream_entry.target.account
 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          link_visibility xml, stream_entry.target
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          stream_entry.target.mentions.each do |mention|
 | 
					          stream_entry.target.mentions.each do |mention|
 | 
				
			||||||
            link_mention xml, mention.account
 | 
					            link_mention xml, mention.account
 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
@@ -204,25 +211,34 @@ module AtomBuilderHelper
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    link_visibility xml, stream_entry.activity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stream_entry.mentions.each do |mentioned|
 | 
					    stream_entry.mentions.each do |mentioned|
 | 
				
			||||||
      link_mention xml, mentioned
 | 
					      link_mention xml, mentioned
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if stream_entry.activity.is_a?(Status)
 | 
					    return unless stream_entry.activity.is_a?(Status)
 | 
				
			||||||
      stream_entry.activity.media_attachments.each do |media|
 | 
					 | 
				
			||||||
        link_enclosure xml, media
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      stream_entry.activity.tags.each do |tag|
 | 
					    stream_entry.activity.media_attachments.each do |media|
 | 
				
			||||||
        category xml, tag
 | 
					      link_enclosure xml, media
 | 
				
			||||||
      end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    stream_entry.activity.tags.each do |tag|
 | 
				
			||||||
 | 
					      category xml, tag
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def root_tag(xml, tag, &block)
 | 
					  def root_tag(xml, tag, &block)
 | 
				
			||||||
    xml.send(tag, { :xmlns => 'http://www.w3.org/2005/Atom', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:media' => 'http://purl.org/syndication/atommedia' }, &block)
 | 
					    xml.send(tag, {
 | 
				
			||||||
 | 
					               'xmlns'          => TagManager::XMLNS,
 | 
				
			||||||
 | 
					               'xmlns:thr'      => TagManager::THR_XMLNS,
 | 
				
			||||||
 | 
					               'xmlns:activity' => TagManager::AS_XMLNS,
 | 
				
			||||||
 | 
					               'xmlns:poco'     => TagManager::POCO_XMLNS,
 | 
				
			||||||
 | 
					               'xmlns:media'    => TagManager::MEDIA_XMLNS,
 | 
				
			||||||
 | 
					               'xmlns:ostatus'  => TagManager::OS_XMLNS,
 | 
				
			||||||
 | 
					             }, &block)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def single_link_avatar(xml, account, size, px)
 | 
					  def single_link_avatar(xml, account, size, px)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,37 @@ class TagManager
 | 
				
			|||||||
  include Singleton
 | 
					  include Singleton
 | 
				
			||||||
  include RoutingHelper
 | 
					  include RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  VERBS = {
 | 
				
			||||||
 | 
					    post:       'http://activitystrea.ms/schema/1.0/post',
 | 
				
			||||||
 | 
					    share:      'http://activitystrea.ms/schema/1.0/share',
 | 
				
			||||||
 | 
					    favorite:   'http://activitystrea.ms/schema/1.0/favorite',
 | 
				
			||||||
 | 
					    unfavorite: 'http://activitystrea.ms/schema/1.0/unfavorite',
 | 
				
			||||||
 | 
					    delete:     'delete',
 | 
				
			||||||
 | 
					    follow:     'http://activitystrea.ms/schema/1.0/follow',
 | 
				
			||||||
 | 
					    unfollow:   'http://ostatus.org/schema/1.0/unfollow',
 | 
				
			||||||
 | 
					  }.freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TYPES = {
 | 
				
			||||||
 | 
					    activity:   'http://activitystrea.ms/schema/1.0/activity',
 | 
				
			||||||
 | 
					    note:       'http://activitystrea.ms/schema/1.0/note',
 | 
				
			||||||
 | 
					    comment:    'http://activitystrea.ms/schema/1.0/comment',
 | 
				
			||||||
 | 
					    person:     'http://activitystrea.ms/schema/1.0/person',
 | 
				
			||||||
 | 
					    collection: 'http://activitystrea.ms/schema/1.0/collection',
 | 
				
			||||||
 | 
					    group:      'http://activitystrea.ms/schema/1.0/group',
 | 
				
			||||||
 | 
					  }.freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  COLLECTIONS = {
 | 
				
			||||||
 | 
					    public: 'http://activityschema.org/collection/public',
 | 
				
			||||||
 | 
					  }.freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  XMLNS       = 'http://www.w3.org/2005/Atom'
 | 
				
			||||||
 | 
					  MEDIA_XMLNS = 'http://purl.org/syndication/atommedia'
 | 
				
			||||||
 | 
					  AS_XMLNS    = 'http://activitystrea.ms/spec/1.0/'
 | 
				
			||||||
 | 
					  THR_XMLNS   = 'http://purl.org/syndication/thread/1.0'
 | 
				
			||||||
 | 
					  POCO_XMLNS  = 'http://portablecontacts.net/spec/1.0'
 | 
				
			||||||
 | 
					  DFRN_XMLNS  = 'http://purl.org/macgirvin/dfrn/1.0'
 | 
				
			||||||
 | 
					  OS_XMLNS    = 'http://ostatus.org/schema/1.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unique_tag(date, id, type)
 | 
					  def unique_tag(date, id, type)
 | 
				
			||||||
    "tag:#{Rails.configuration.x.local_domain},#{date.strftime('%Y-%m-%d')}:objectId=#{id}:objectType=#{type}"
 | 
					    "tag:#{Rails.configuration.x.local_domain},#{date.strftime('%Y-%m-%d')}:objectId=#{id}:objectType=#{type}"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@ class Status < ApplicationRecord
 | 
				
			|||||||
  include Streamable
 | 
					  include Streamable
 | 
				
			||||||
  include Cacheable
 | 
					  include Cacheable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  enum visibility: [:public, :unlisted], _suffix: :visibility
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  belongs_to :account, inverse_of: :statuses
 | 
					  belongs_to :account, inverse_of: :statuses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  belongs_to :thread, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :replies
 | 
					  belongs_to :thread, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :replies
 | 
				
			||||||
@@ -100,6 +102,7 @@ class Status < ApplicationRecord
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def as_public_timeline(account = nil)
 | 
					    def as_public_timeline(account = nil)
 | 
				
			||||||
      query = joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
 | 
					      query = joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
 | 
				
			||||||
 | 
					              .where(visibility: :public)
 | 
				
			||||||
              .where('accounts.silenced = FALSE')
 | 
					              .where('accounts.silenced = FALSE')
 | 
				
			||||||
              .where('statuses.in_reply_to_id IS NULL')
 | 
					              .where('statuses.in_reply_to_id IS NULL')
 | 
				
			||||||
              .where('statuses.reblog_of_id IS NULL')
 | 
					              .where('statuses.reblog_of_id IS NULL')
 | 
				
			||||||
@@ -110,6 +113,7 @@ class Status < ApplicationRecord
 | 
				
			|||||||
    def as_tag_timeline(tag, account = nil)
 | 
					    def as_tag_timeline(tag, account = nil)
 | 
				
			||||||
      query = tag.statuses
 | 
					      query = tag.statuses
 | 
				
			||||||
                 .joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
 | 
					                 .joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
 | 
				
			||||||
 | 
					                 .where(visibility: :public)
 | 
				
			||||||
                 .where('accounts.silenced = FALSE')
 | 
					                 .where('accounts.silenced = FALSE')
 | 
				
			||||||
                 .where('statuses.in_reply_to_id IS NULL')
 | 
					                 .where('statuses.in_reply_to_id IS NULL')
 | 
				
			||||||
                 .where('statuses.reblog_of_id IS NULL')
 | 
					                 .where('statuses.reblog_of_id IS NULL')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ class FanOutOnWriteService < BaseService
 | 
				
			|||||||
    deliver_to_followers(status)
 | 
					    deliver_to_followers(status)
 | 
				
			||||||
    deliver_to_mentioned(status)
 | 
					    deliver_to_mentioned(status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if status.account.silenced?
 | 
					    return if status.account.silenced? || !status.public_visibility?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    deliver_to_hashtags(status)
 | 
					    deliver_to_hashtags(status)
 | 
				
			||||||
    deliver_to_public(status)
 | 
					    deliver_to_public(status)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ class PostStatusService < BaseService
 | 
				
			|||||||
  # @option [Enumerable] :media_ids Optional array of media IDs to attach
 | 
					  # @option [Enumerable] :media_ids Optional array of media IDs to attach
 | 
				
			||||||
  # @return [Status]
 | 
					  # @return [Status]
 | 
				
			||||||
  def call(account, text, in_reply_to = nil, options = {})
 | 
					  def call(account, text, in_reply_to = nil, options = {})
 | 
				
			||||||
    status = account.statuses.create!(text: text, thread: in_reply_to, sensitive: options[:sensitive])
 | 
					    status = account.statuses.create!(text: text, thread: in_reply_to, sensitive: options[:sensitive], visibility: options[:unlisted] ? :unlisted : :public)
 | 
				
			||||||
    attach_media(status, options[:media_ids])
 | 
					    attach_media(status, options[:media_ids])
 | 
				
			||||||
    process_mentions_service.call(status)
 | 
					    process_mentions_service.call(status)
 | 
				
			||||||
    process_hashtags_service.call(status)
 | 
					    process_hashtags_service.call(status)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,6 @@
 | 
				
			|||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProcessFeedService < BaseService
 | 
					class ProcessFeedService < BaseService
 | 
				
			||||||
  ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'
 | 
					 | 
				
			||||||
  THREAD_NS   = 'http://purl.org/syndication/thread/1.0'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call(body, account)
 | 
					  def call(body, account)
 | 
				
			||||||
    xml = Nokogiri::XML(body)
 | 
					    xml = Nokogiri::XML(body)
 | 
				
			||||||
    xml.encoding = 'utf-8'
 | 
					    xml.encoding = 'utf-8'
 | 
				
			||||||
@@ -15,12 +12,12 @@ class ProcessFeedService < BaseService
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update_author(xml, account)
 | 
					  def update_author(xml, account)
 | 
				
			||||||
    return if xml.at_xpath('/xmlns:feed').nil?
 | 
					    return if xml.at_xpath('/xmlns:feed', xmlns: TagManager::XMLNS).nil?
 | 
				
			||||||
    UpdateRemoteProfileService.new.call(xml.at_xpath('/xmlns:feed'), account, true)
 | 
					    UpdateRemoteProfileService.new.call(xml.at_xpath('/xmlns:feed', xmlns: TagManager::XMLNS), account, true)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def process_entries(xml, account)
 | 
					  def process_entries(xml, account)
 | 
				
			||||||
    xml.xpath('//xmlns:entry').reverse_each.map { |entry| ProcessEntry.new.call(entry, account) }.compact
 | 
					    xml.xpath('//xmlns:entry', xmlns: TagManager::XMLNS).reverse_each.map { |entry| ProcessEntry.new.call(entry, account) }.compact
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  class ProcessEntry
 | 
					  class ProcessEntry
 | 
				
			||||||
@@ -48,7 +45,7 @@ class ProcessFeedService < BaseService
 | 
				
			|||||||
      status = status_from_xml(@xml)
 | 
					      status = status_from_xml(@xml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if verb == :share
 | 
					      if verb == :share
 | 
				
			||||||
        original_status = status_from_xml(@xml.at_xpath('.//activity:object', activity: ACTIVITY_NS))
 | 
					        original_status = status_from_xml(@xml.at_xpath('.//activity:object', activity: TagManager::AS_XMLNS))
 | 
				
			||||||
        status.reblog   = original_status
 | 
					        status.reblog   = original_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if original_status.nil?
 | 
					        if original_status.nil?
 | 
				
			||||||
@@ -138,9 +135,15 @@ class ProcessFeedService < BaseService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def mentions_from_xml(parent, xml)
 | 
					    def mentions_from_xml(parent, xml)
 | 
				
			||||||
      processed_account_ids = []
 | 
					      processed_account_ids = []
 | 
				
			||||||
 | 
					      public_visibility     = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      xml.xpath('./xmlns:link[@rel="mentioned"]').each do |link|
 | 
					      xml.xpath('./xmlns:link[@rel="mentioned"]', xmlns: TagManager::XMLNS).each do |link|
 | 
				
			||||||
        next if link['href'] == 'http://activityschema.org/collection/public'
 | 
					        if link['ostatus:object-type'] == TagManager::TYPES[:collection] && link['href'] == TagManager::COLLECTIONS[:public]
 | 
				
			||||||
 | 
					          public_visibility = true
 | 
				
			||||||
 | 
					          next
 | 
				
			||||||
 | 
					        elsif link['ostatus:object-type'] == TagManager::TYPES[:group]
 | 
				
			||||||
 | 
					          next
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        url = Addressable::URI.parse(link['href'])
 | 
					        url = Addressable::URI.parse(link['href'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -160,15 +163,18 @@ class ProcessFeedService < BaseService
 | 
				
			|||||||
        # So we can skip duplicate mentions
 | 
					        # So we can skip duplicate mentions
 | 
				
			||||||
        processed_account_ids << mentioned_account.id
 | 
					        processed_account_ids << mentioned_account.id
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      parent.visibility = public_visibility ? :public : :unlisted
 | 
				
			||||||
 | 
					      parent.save!
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def hashtags_from_xml(parent, xml)
 | 
					    def hashtags_from_xml(parent, xml)
 | 
				
			||||||
      tags = xml.xpath('./xmlns:category').map { |category| category['term'] }.select { |t| !t.blank? }
 | 
					      tags = xml.xpath('./xmlns:category', xmlns: TagManager::XMLNS).map { |category| category['term'] }.select { |t| !t.blank? }
 | 
				
			||||||
      ProcessHashtagsService.new.call(parent, tags)
 | 
					      ProcessHashtagsService.new.call(parent, tags)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def media_from_xml(parent, xml)
 | 
					    def media_from_xml(parent, xml)
 | 
				
			||||||
      xml.xpath('./xmlns:link[@rel="enclosure"]').each do |link|
 | 
					      xml.xpath('./xmlns:link[@rel="enclosure"]', xmlns: TagManager::XMLNS).each do |link|
 | 
				
			||||||
        next unless link['href']
 | 
					        next unless link['href']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        media = MediaAttachment.where(status: parent, remote_url: link['href']).first_or_initialize(account: parent.account, status: parent, remote_url: link['href'])
 | 
					        media = MediaAttachment.where(status: parent, remote_url: link['href']).first_or_initialize(account: parent.account, status: parent, remote_url: link['href'])
 | 
				
			||||||
@@ -183,52 +189,52 @@ class ProcessFeedService < BaseService
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def id(xml = @xml)
 | 
					    def id(xml = @xml)
 | 
				
			||||||
      xml.at_xpath('./xmlns:id').content
 | 
					      xml.at_xpath('./xmlns:id', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def verb(xml = @xml)
 | 
					    def verb(xml = @xml)
 | 
				
			||||||
      raw = xml.at_xpath('./activity:verb', activity: ACTIVITY_NS).content
 | 
					      raw = xml.at_xpath('./activity:verb', activity: TagManager::AS_XMLNS).content
 | 
				
			||||||
      raw.gsub('http://activitystrea.ms/schema/1.0/', '').gsub('http://ostatus.org/schema/1.0/', '').to_sym
 | 
					      TagManager::VERBS.key(raw)
 | 
				
			||||||
    rescue
 | 
					    rescue
 | 
				
			||||||
      :post
 | 
					      :post
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def type(xml = @xml)
 | 
					    def type(xml = @xml)
 | 
				
			||||||
      raw = xml.at_xpath('./activity:object-type', activity: ACTIVITY_NS).content
 | 
					      raw = xml.at_xpath('./activity:object-type', activity: TagManager::AS_XMLNS).content
 | 
				
			||||||
      raw.gsub('http://activitystrea.ms/schema/1.0/', '').gsub('http://ostatus.org/schema/1.0/', '').to_sym
 | 
					      TagManager::TYPES.key(raw)
 | 
				
			||||||
    rescue
 | 
					    rescue
 | 
				
			||||||
      :activity
 | 
					      :activity
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def url(xml = @xml)
 | 
					    def url(xml = @xml)
 | 
				
			||||||
      link = xml.at_xpath('./xmlns:link[@rel="alternate"]')
 | 
					      link = xml.at_xpath('./xmlns:link[@rel="alternate"]', xmlns: TagManager::XMLNS)
 | 
				
			||||||
      link.nil? ? nil : link['href']
 | 
					      link.nil? ? nil : link['href']
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def content(xml = @xml)
 | 
					    def content(xml = @xml)
 | 
				
			||||||
      xml.at_xpath('./xmlns:content').content
 | 
					      xml.at_xpath('./xmlns:content', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def published(xml = @xml)
 | 
					    def published(xml = @xml)
 | 
				
			||||||
      xml.at_xpath('./xmlns:published').content
 | 
					      xml.at_xpath('./xmlns:published', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def thread?(xml = @xml)
 | 
					    def thread?(xml = @xml)
 | 
				
			||||||
      !xml.at_xpath('./thr:in-reply-to', thr: THREAD_NS).nil?
 | 
					      !xml.at_xpath('./thr:in-reply-to', thr: TagManager::THR_XMLNS).nil?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def thread(xml = @xml)
 | 
					    def thread(xml = @xml)
 | 
				
			||||||
      thr = xml.at_xpath('./thr:in-reply-to', thr: THREAD_NS)
 | 
					      thr = xml.at_xpath('./thr:in-reply-to', thr: TagManager::THR_XMLNS)
 | 
				
			||||||
      [thr['ref'], thr['href']]
 | 
					      [thr['ref'], thr['href']]
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def account?(xml = @xml)
 | 
					    def account?(xml = @xml)
 | 
				
			||||||
      !xml.at_xpath('./xmlns:author').nil?
 | 
					      !xml.at_xpath('./xmlns:author', xmlns: TagManager::XMLNS).nil?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def acct(xml = @xml)
 | 
					    def acct(xml = @xml)
 | 
				
			||||||
      username = xml.at_xpath('./xmlns:author/xmlns:name').content
 | 
					      username = xml.at_xpath('./xmlns:author/xmlns:name', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
      url      = xml.at_xpath('./xmlns:author/xmlns:uri').content
 | 
					      url      = xml.at_xpath('./xmlns:author/xmlns:uri', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
      domain   = Addressable::URI.parse(url).host
 | 
					      domain   = Addressable::URI.parse(url).host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      "#{username}@#{domain}"
 | 
					      "#{username}@#{domain}"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,6 @@
 | 
				
			|||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProcessInteractionService < BaseService
 | 
					class ProcessInteractionService < BaseService
 | 
				
			||||||
  ACTIVITY_NS = 'http://activitystrea.ms/spec/1.0/'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Record locally the remote interaction with our user
 | 
					  # Record locally the remote interaction with our user
 | 
				
			||||||
  # @param [String] envelope Salmon envelope
 | 
					  # @param [String] envelope Salmon envelope
 | 
				
			||||||
  # @param [Account] target_account Account the Salmon was addressed to
 | 
					  # @param [Account] target_account Account the Salmon was addressed to
 | 
				
			||||||
@@ -14,8 +12,8 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return unless contains_author?(xml)
 | 
					    return unless contains_author?(xml)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    username = xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:name').content
 | 
					    username = xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:name', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
    url      = xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:uri').content
 | 
					    url      = xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:uri', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
    domain   = Addressable::URI.parse(url).host
 | 
					    domain   = Addressable::URI.parse(url).host
 | 
				
			||||||
    account  = Account.find_by(username: username, domain: domain)
 | 
					    account  = Account.find_by(username: username, domain: domain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,7 +24,7 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if salmon.verify(envelope, account.keypair)
 | 
					    if salmon.verify(envelope, account.keypair)
 | 
				
			||||||
      update_remote_profile_service.call(xml.at_xpath('/xmlns:entry'), account, true)
 | 
					      update_remote_profile_service.call(xml.at_xpath('/xmlns:entry', xmlns: TagManager::XMLNS), account, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case verb(xml)
 | 
					      case verb(xml)
 | 
				
			||||||
      when :follow
 | 
					      when :follow
 | 
				
			||||||
@@ -50,16 +48,17 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def contains_author?(xml)
 | 
					  def contains_author?(xml)
 | 
				
			||||||
    !(xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:name').nil? || xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:uri').nil?)
 | 
					    !(xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:name', xmlns: TagManager::XMLNS).nil? || xml.at_xpath('/xmlns:entry/xmlns:author/xmlns:uri', xmlns: TagManager::XMLNS).nil?)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def mentions_account?(xml, account)
 | 
					  def mentions_account?(xml, account)
 | 
				
			||||||
    xml.xpath('/xmlns:entry/xmlns:link[@rel="mentioned"]').each { |mention_link| return true if mention_link.attribute('href').value == TagManager.instance.url_for(account) }
 | 
					    xml.xpath('/xmlns:entry/xmlns:link[@rel="mentioned"]', xmlns: TagManager::XMLNS).each { |mention_link| return true if mention_link.attribute('href').value == TagManager.instance.url_for(account) }
 | 
				
			||||||
    false
 | 
					    false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def verb(xml)
 | 
					  def verb(xml)
 | 
				
			||||||
    xml.at_xpath('//activity:verb', activity: ACTIVITY_NS).content.gsub('http://activitystrea.ms/schema/1.0/', '').gsub('http://ostatus.org/schema/1.0/', '').to_sym
 | 
					    raw = xml.at_xpath('//activity:verb', activity: TagManager::AS_XMLNS).content
 | 
				
			||||||
 | 
					    TagManager::VERBS.key(raw)
 | 
				
			||||||
  rescue
 | 
					  rescue
 | 
				
			||||||
    :post
 | 
					    :post
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@@ -74,7 +73,7 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def delete_post!(xml, account)
 | 
					  def delete_post!(xml, account)
 | 
				
			||||||
    status = Status.find(xml.at_xpath('//xmlns:id').content)
 | 
					    status = Status.find(xml.at_xpath('//xmlns:id', xmlns: TagManager::XMLNS).content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if status.nil?
 | 
					    return if status.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,7 +95,7 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def activity_id(xml)
 | 
					  def activity_id(xml)
 | 
				
			||||||
    xml.at_xpath('//activity:object', activity: ACTIVITY_NS).at_xpath('./xmlns:id').content
 | 
					    xml.at_xpath('//activity:object', activity: TagManager::AS_XMLNS).at_xpath('./xmlns:id', xmlns: TagManager::XMLNS).content
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def salmon
 | 
					  def salmon
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,19 +1,16 @@
 | 
				
			|||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UpdateRemoteProfileService < BaseService
 | 
					class UpdateRemoteProfileService < BaseService
 | 
				
			||||||
  POCO_NS = 'http://portablecontacts.net/spec/1.0'
 | 
					 | 
				
			||||||
  DFRN_NS = 'http://purl.org/macgirvin/dfrn/1.0'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def call(xml, account, resubscribe = false)
 | 
					  def call(xml, account, resubscribe = false)
 | 
				
			||||||
    return if xml.nil?
 | 
					    return if xml.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    author_xml = xml.at_xpath('./xmlns:author') || xml.at_xpath('./dfrn:owner', dfrn: DFRN_NS)
 | 
					    author_xml = xml.at_xpath('./xmlns:author', xmlns: TagManager::XMLNS) || xml.at_xpath('./dfrn:owner', dfrn: TagManager::DFRN_XMLNS)
 | 
				
			||||||
    hub_link   = xml.at_xpath('./xmlns:link[@rel="hub"]')
 | 
					    hub_link   = xml.at_xpath('./xmlns:link[@rel="hub"]', xmlns: TagManager::XMLNS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unless author_xml.nil?
 | 
					    unless author_xml.nil?
 | 
				
			||||||
      account.display_name      = author_xml.at_xpath('./poco:displayName', poco: POCO_NS).content unless author_xml.at_xpath('./poco:displayName', poco: POCO_NS).nil?
 | 
					      account.display_name      = author_xml.at_xpath('./poco:displayName', poco: TagManager::POCO_XMLNS).content unless author_xml.at_xpath('./poco:displayName', poco: TagManager::POCO_XMLNS).nil?
 | 
				
			||||||
      account.note              = author_xml.at_xpath('./poco:note', poco: POCO_NS).content unless author_xml.at_xpath('./poco:note').nil?
 | 
					      account.note              = author_xml.at_xpath('./poco:note', poco: TagManager::POCO_XMLNS).content unless author_xml.at_xpath('./poco:note', poco: TagManager::POCO_XMLNS).nil?
 | 
				
			||||||
      account.avatar_remote_url = author_xml.at_xpath('./xmlns:link[@rel="avatar"]')['href'] unless author_xml.at_xpath('./xmlns:link[@rel="avatar"]').nil? || author_xml.at_xpath('./xmlns:link[@rel="avatar"]')['href'].blank?
 | 
					      account.avatar_remote_url = author_xml.at_xpath('./xmlns:link[@rel="avatar"]', xmlns: TagManager::XMLNS)['href'] unless author_xml.at_xpath('./xmlns:link[@rel="avatar"]', xmlns: TagManager::XMLNS).nil? || author_xml.at_xpath('./xmlns:link[@rel="avatar"]', xmlns: TagManager::XMLNS)['href'].blank?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    old_hub_url     = account.hub_url
 | 
					    old_hub_url     = account.hub_url
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,6 @@
 | 
				
			|||||||
  = f.input :note, placeholder: t('simple_form.labels.defaults.note')
 | 
					  = f.input :note, placeholder: t('simple_form.labels.defaults.note')
 | 
				
			||||||
  = f.input :avatar, wrapper: :with_label
 | 
					  = f.input :avatar, wrapper: :with_label
 | 
				
			||||||
  = f.input :header, wrapper: :with_label
 | 
					  = f.input :header, wrapper: :with_label
 | 
				
			||||||
  = f.input :silenced, as: :boolean, wrapper: :with_label
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .actions
 | 
					  .actions
 | 
				
			||||||
    = f.button :button, t('generic.save_changes'), type: :submit
 | 
					    = f.button :button, t('generic.save_changes'), type: :submit
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ de:
 | 
				
			|||||||
        new_password: Neues Passwort
 | 
					        new_password: Neues Passwort
 | 
				
			||||||
        note: Über mich
 | 
					        note: Über mich
 | 
				
			||||||
        password: Passwort
 | 
					        password: Passwort
 | 
				
			||||||
        silenced: Öffentliche Beiträge nicht auflisten
 | 
					 | 
				
			||||||
        username: Nutzername
 | 
					        username: Nutzername
 | 
				
			||||||
      interactions:
 | 
					      interactions:
 | 
				
			||||||
        must_be_follower: Benachrichtigungen von nicht-Folgern blockieren
 | 
					        must_be_follower: Benachrichtigungen von nicht-Folgern blockieren
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ en:
 | 
				
			|||||||
        new_password: New password
 | 
					        new_password: New password
 | 
				
			||||||
        note: Bio
 | 
					        note: Bio
 | 
				
			||||||
        password: Password
 | 
					        password: Password
 | 
				
			||||||
        silenced: Unlisted mode
 | 
					 | 
				
			||||||
        username: Username
 | 
					        username: Username
 | 
				
			||||||
      interactions:
 | 
					      interactions:
 | 
				
			||||||
        must_be_follower: Block notifications from non-followers
 | 
					        must_be_follower: Block notifications from non-followers
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ es:
 | 
				
			|||||||
        new_password: Nueva contraseña
 | 
					        new_password: Nueva contraseña
 | 
				
			||||||
        note: Biografía
 | 
					        note: Biografía
 | 
				
			||||||
        password: Contraseña
 | 
					        password: Contraseña
 | 
				
			||||||
        silenced: No listado
 | 
					 | 
				
			||||||
        username: Nombre de usuario
 | 
					        username: Nombre de usuario
 | 
				
			||||||
      notification_emails:
 | 
					      notification_emails:
 | 
				
			||||||
        favourite: Enviar correo electrónico cuando alguien de a favorito en su publicación
 | 
					        favourite: Enviar correo electrónico cuando alguien de a favorito en su publicación
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ fr:
 | 
				
			|||||||
        new_password: Nouveau mot de passe
 | 
					        new_password: Nouveau mot de passe
 | 
				
			||||||
        note: Présentation
 | 
					        note: Présentation
 | 
				
			||||||
        password: Mot de passe
 | 
					        password: Mot de passe
 | 
				
			||||||
        silenced: Ne pas apparaître dans le fil public
 | 
					 | 
				
			||||||
        username: Identifiant
 | 
					        username: Identifiant
 | 
				
			||||||
      interactions:
 | 
					      interactions:
 | 
				
			||||||
        must_be_follower: Masquer les notifications des personnes qui ne vous suivent pas
 | 
					        must_be_follower: Masquer les notifications des personnes qui ne vous suivent pas
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@ hu:
 | 
				
			|||||||
        new_password: Új jelszó
 | 
					        new_password: Új jelszó
 | 
				
			||||||
        note: Önéletrajz
 | 
					        note: Önéletrajz
 | 
				
			||||||
        password: Jelszó
 | 
					        password: Jelszó
 | 
				
			||||||
        silenced: Listázatlan mód
 | 
					 | 
				
			||||||
        username: Felhasználónév
 | 
					        username: Felhasználónév
 | 
				
			||||||
      notification_emails:
 | 
					      notification_emails:
 | 
				
			||||||
        favourite: E-mail küldése amikor valaki kedvencnek jelöli az állapotod
 | 
					        favourite: E-mail küldése amikor valaki kedvencnek jelöli az állapotod
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								db/migrate/20161130185319_add_visibility_to_statuses.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								db/migrate/20161130185319_add_visibility_to_statuses.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					class AddVisibilityToStatuses < ActiveRecord::Migration[5.0]
 | 
				
			||||||
 | 
					  def change
 | 
				
			||||||
 | 
					    add_column :statuses, :visibility, :integer, null: false, default: 0
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# It's strongly recommended that you check this file into your version control system.
 | 
					# It's strongly recommended that you check this file into your version control system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ActiveRecord::Schema.define(version: 20161130142058) do
 | 
					ActiveRecord::Schema.define(version: 20161130185319) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # These are extensions that must be enabled in order to support this database
 | 
					  # These are extensions that must be enabled in order to support this database
 | 
				
			||||||
  enable_extension "plpgsql"
 | 
					  enable_extension "plpgsql"
 | 
				
			||||||
@@ -176,6 +176,7 @@ ActiveRecord::Schema.define(version: 20161130142058) do
 | 
				
			|||||||
    t.integer  "reblog_of_id"
 | 
					    t.integer  "reblog_of_id"
 | 
				
			||||||
    t.string   "url"
 | 
					    t.string   "url"
 | 
				
			||||||
    t.boolean  "sensitive",      default: false
 | 
					    t.boolean  "sensitive",      default: false
 | 
				
			||||||
 | 
					    t.integer  "visibility",     default: 0,     null: false
 | 
				
			||||||
    t.index ["account_id"], name: "index_statuses_on_account_id", using: :btree
 | 
					    t.index ["account_id"], name: "index_statuses_on_account_id", using: :btree
 | 
				
			||||||
    t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id", using: :btree
 | 
					    t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id", using: :btree
 | 
				
			||||||
    t.index ["reblog_of_id"], name: "index_statuses_on_reblog_of_id", using: :btree
 | 
					    t.index ["reblog_of_id"], name: "index_statuses_on_reblog_of_id", using: :btree
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ RSpec.describe AtomBuilderHelper, type: :helper do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  describe '#feed' do
 | 
					  describe '#feed' do
 | 
				
			||||||
    it 'creates a feed' do
 | 
					    it 'creates a feed' do
 | 
				
			||||||
      expect(used_in_builder { |xml| helper.feed(xml) }).to match '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia"/>'
 | 
					      expect(used_in_builder { |xml| helper.feed(xml) }).to match '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0"/>'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,7 +46,7 @@ RSpec.describe AtomBuilderHelper, type: :helper do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  describe '#verb' do
 | 
					  describe '#verb' do
 | 
				
			||||||
    it 'creates an entry' do
 | 
					    it 'creates an entry' do
 | 
				
			||||||
      expect(used_with_namespaces { |xml| helper.verb(xml, 'verb') }).to match '<activity:verb>http://activitystrea.ms/schema/1.0/verb</activity:verb>'
 | 
					      expect(used_with_namespaces { |xml| helper.verb(xml, :post) }).to match '<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,7 +76,7 @@ RSpec.describe AtomBuilderHelper, type: :helper do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  describe '#object_type' do
 | 
					  describe '#object_type' do
 | 
				
			||||||
    it 'creates an object type' do
 | 
					    it 'creates an object type' do
 | 
				
			||||||
      expect(used_with_namespaces { |xml| helper.object_type(xml, 'test') }).to match '<activity:object-type>http://activitystrea.ms/schema/1.0/test</activity:object-type>'
 | 
					      expect(used_with_namespaces { |xml| helper.object_type(xml, :person) }).to match '<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,7 +146,7 @@ RSpec.describe AtomBuilderHelper, type: :helper do
 | 
				
			|||||||
    let(:account) { Fabricate(:account, username: 'alice') }
 | 
					    let(:account) { Fabricate(:account, username: 'alice') }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it 'creates a link' do
 | 
					    it 'creates a link' do
 | 
				
			||||||
      expect(used_in_builder { |xml| helper.link_mention(xml, account) }).to match '<link rel="mentioned" href="https://cb6e6126.ngrok.io/users/alice"/>'
 | 
					      expect(used_in_builder { |xml| helper.link_mention(xml, account) }).to match '<link rel="mentioned" href="https://cb6e6126.ngrok.io/users/alice" ostatus:object-type="http://activitystrea.ms/schema/1.0/person"/>'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user