Merge branch 'master' into patch-4
This commit is contained in:
		
						commit
						0c4e9fdda0
					
				
					 30 changed files with 433 additions and 269 deletions
				
			
		|  | @ -1,8 +1,13 @@ | ||||||
| FROM ruby:2.3.1-alpine | FROM ruby:2.3.1-alpine | ||||||
| 
 | 
 | ||||||
|  | LABEL maintainer="https://github.com/tootsuite/mastodon" \ | ||||||
|  |       description="A GNU Social-compatible microblogging server" | ||||||
|  | 
 | ||||||
| ENV RAILS_ENV=production \ | ENV RAILS_ENV=production \ | ||||||
|     NODE_ENV=production |     NODE_ENV=production | ||||||
| 
 | 
 | ||||||
|  | EXPOSE 3000 4000 | ||||||
|  | 
 | ||||||
| WORKDIR /mastodon | WORKDIR /mastodon | ||||||
| 
 | 
 | ||||||
| COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/ | COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/ | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Gemfile
									
										
									
									
									
								
							|  | @ -34,6 +34,7 @@ gem 'doorkeeper' | ||||||
| gem 'rabl' | gem 'rabl' | ||||||
| gem 'rqrcode' | gem 'rqrcode' | ||||||
| gem 'twitter-text' | gem 'twitter-text' | ||||||
|  | gem 'ox' | ||||||
| gem 'oj' | gem 'oj' | ||||||
| gem 'hiredis' | gem 'hiredis' | ||||||
| gem 'redis', '~>3.2', require: ['redis', 'redis/connection/hiredis'] | gem 'redis', '~>3.2', require: ['redis', 'redis/connection/hiredis'] | ||||||
|  |  | ||||||
|  | @ -240,6 +240,7 @@ GEM | ||||||
|       addressable (~> 2.4) |       addressable (~> 2.4) | ||||||
|       http (~> 2.0) |       http (~> 2.0) | ||||||
|       nokogiri (~> 1.6) |       nokogiri (~> 1.6) | ||||||
|  |     ox (2.4.11) | ||||||
|     paperclip (5.1.0) |     paperclip (5.1.0) | ||||||
|       activemodel (>= 4.2.0) |       activemodel (>= 4.2.0) | ||||||
|       activesupport (>= 4.2.0) |       activesupport (>= 4.2.0) | ||||||
|  | @ -482,6 +483,7 @@ DEPENDENCIES | ||||||
|   nokogiri |   nokogiri | ||||||
|   oj |   oj | ||||||
|   ostatus2 |   ostatus2 | ||||||
|  |   ox | ||||||
|   paperclip (~> 5.1) |   paperclip (~> 5.1) | ||||||
|   paperclip-av-transcoder |   paperclip-av-transcoder | ||||||
|   pg |   pg | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								Procfile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Procfile
									
										
									
									
									
								
							|  | @ -1,2 +1,2 @@ | ||||||
| web: bundle exec puma -C config/puma.rb | web: bundle exec puma -C config/puma.rb | ||||||
| worker: bundle exec sidekiq -q default -q mailers -q push | worker: bundle exec sidekiq -q default -q push -q pull -q mailers | ||||||
|  |  | ||||||
|  | @ -65,6 +65,8 @@ Consult the example configuration file, `.env.production.sample` for the full li | ||||||
| 
 | 
 | ||||||
| ## Running with Docker and Docker-Compose | ## Running with Docker and Docker-Compose | ||||||
| 
 | 
 | ||||||
|  | [](https://microbadger.com/images/gargron/mastodon "Get your own version badge on microbadger.com") [](https://microbadger.com/images/gargron/mastodon "Get your own image badge on microbadger.com") | ||||||
|  | 
 | ||||||
| The project now includes a `Dockerfile` and a `docker-compose.yml`. You need to turn `.env.production.sample` into `.env.production` with all the variables set before you can: | The project now includes a `Dockerfile` and a `docker-compose.yml`. You need to turn `.env.production.sample` into `.env.production` with all the variables set before you can: | ||||||
| 
 | 
 | ||||||
|     docker-compose build |     docker-compose build | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								Vagrantfile
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								Vagrantfile
									
										
									
									
										vendored
									
									
								
							|  | @ -84,6 +84,16 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| | ||||||
|   config.vm.provider :virtualbox do |vb| |   config.vm.provider :virtualbox do |vb| | ||||||
|     vb.name = "mastodon" |     vb.name = "mastodon" | ||||||
|     vb.customize ["modifyvm", :id, "--memory", "1024"] |     vb.customize ["modifyvm", :id, "--memory", "1024"] | ||||||
|  | 
 | ||||||
|  |     # Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions. | ||||||
|  |     # https://github.com/mitchellh/vagrant/issues/1172 | ||||||
|  |     vb.customize ["modifyvm", :id, "--natdnsproxy1", "off"] | ||||||
|  |     vb.customize ["modifyvm", :id, "--natdnshostresolver1", "off"] | ||||||
|  | 
 | ||||||
|  |     # Use "virtio" network interfaces for better performance. | ||||||
|  |     vb.customize ["modifyvm", :id, "--nictype1", "virtio"] | ||||||
|  |     vb.customize ["modifyvm", :id, "--nictype2", "virtio"] | ||||||
|  | 
 | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   config.vm.hostname = "mastodon.dev" |   config.vm.hostname = "mastodon.dev" | ||||||
|  | @ -91,9 +101,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| | ||||||
|   # This uses the vagrant-hostsupdater plugin, and lets you |   # This uses the vagrant-hostsupdater plugin, and lets you | ||||||
|   # access the development site at http://mastodon.dev. |   # access the development site at http://mastodon.dev. | ||||||
|   # To install: |   # To install: | ||||||
|   #   $ vagrant plugin install hostsupdater |   #   $ vagrant plugin install vagrant-hostsupdater | ||||||
|   if defined?(VagrantPlugins::HostsUpdater) |   if defined?(VagrantPlugins::HostsUpdater) | ||||||
|     config.vm.network :private_network, ip: "192.168.42.42" |     config.vm.network :private_network, ip: "192.168.42.42", nictype: "virtio" | ||||||
|     config.hostsupdater.remove_on_suspend = false |     config.hostsupdater.remove_on_suspend = false | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 874 KiB After Width: | Height: | Size: 209 KiB | 
|  | @ -16,7 +16,8 @@ class AccountsController < ApplicationController | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       format.atom do |       format.atom do | ||||||
|         @entries = @account.stream_entries.order('id desc').where(activity_type: 'Status').where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id]) |         @entries = @account.stream_entries.order('id desc').where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id]) | ||||||
|  |         render xml: AtomSerializer.render(AtomSerializer.new.feed(@account, @entries.to_a)) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       format.activitystreams2 |       format.activitystreams2 | ||||||
|  |  | ||||||
|  | @ -19,7 +19,9 @@ class StreamEntriesController < ApplicationController | ||||||
|         end |         end | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       format.atom |       format.atom do | ||||||
|  |         render xml: AtomSerializer.render(AtomSerializer.new.entry(@stream_entry, true)) | ||||||
|  |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										351
									
								
								app/lib/atom_serializer.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								app/lib/atom_serializer.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,351 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AtomSerializer | ||||||
|  |   include RoutingHelper | ||||||
|  | 
 | ||||||
|  |   class << self | ||||||
|  |     def render(element) | ||||||
|  |       document = Ox::Document.new(version: '1.0') | ||||||
|  |       document << element | ||||||
|  |       ('<?xml version="1.0"?>' + Ox.dump(element)).force_encoding('UTF-8') | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def author(account) | ||||||
|  |     author = Ox::Element.new('author') | ||||||
|  | 
 | ||||||
|  |     uri = TagManager.instance.uri_for(account) | ||||||
|  | 
 | ||||||
|  |     append_element(author, 'id', uri) | ||||||
|  |     append_element(author, 'activity:object-type', TagManager::TYPES[:person]) | ||||||
|  |     append_element(author, 'uri', uri) | ||||||
|  |     append_element(author, 'name', account.username) | ||||||
|  |     append_element(author, 'email', account.local? ? "#{account.acct}@#{Rails.configuration.x.local_domain}" : account.acct) | ||||||
|  |     append_element(author, 'summary', account.note) | ||||||
|  |     append_element(author, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(account)) | ||||||
|  |     append_element(author, 'link', nil, rel: :avatar, type: account.avatar_content_type, 'media:width': 120, 'media:height': 120, href: full_asset_url(account.avatar.url(:original))) | ||||||
|  |     append_element(author, 'link', nil, rel: :header, type: account.header_content_type, 'media:width': 700, 'media:height': 335, href: full_asset_url(account.header.url(:original))) | ||||||
|  |     append_element(author, 'poco:preferredUsername', account.username) | ||||||
|  |     append_element(author, 'poco:displayName', account.display_name) unless account.display_name.blank? | ||||||
|  |     append_element(author, 'poco:note', Formatter.instance.simplified_format(account).to_str) unless account.note.blank? | ||||||
|  |     append_element(author, 'mastodon:scope', account.locked? ? :private : :public) | ||||||
|  | 
 | ||||||
|  |     author | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def feed(account, stream_entries) | ||||||
|  |     feed = Ox::Element.new('feed') | ||||||
|  | 
 | ||||||
|  |     add_namespaces(feed) | ||||||
|  | 
 | ||||||
|  |     append_element(feed, 'id', account_url(account, format: 'atom')) | ||||||
|  |     append_element(feed, 'title', account.display_name) | ||||||
|  |     append_element(feed, 'subtitle', account.note) | ||||||
|  |     append_element(feed, 'updated', account.updated_at.iso8601) | ||||||
|  |     append_element(feed, 'logo', full_asset_url(account.avatar.url(:original))) | ||||||
|  | 
 | ||||||
|  |     feed << author(account) | ||||||
|  | 
 | ||||||
|  |     append_element(feed, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(account)) | ||||||
|  |     append_element(feed, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_url(account, format: 'atom')) | ||||||
|  |     append_element(feed, 'link', nil, rel: :next, type: 'application/atom+xml', href: account_url(account, format: 'atom', max_id: stream_entries.last.id)) if stream_entries.size == 20 | ||||||
|  |     append_element(feed, 'link', nil, rel: :hub, href: api_push_url) | ||||||
|  |     append_element(feed, 'link', nil, rel: :salmon, href: api_salmon_url(account.id)) | ||||||
|  | 
 | ||||||
|  |     stream_entries.each do |stream_entry| | ||||||
|  |       feed << entry(stream_entry) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     feed | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def entry(stream_entry, root = false) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  | 
 | ||||||
|  |     add_namespaces(entry) if root | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type)) | ||||||
|  |     append_element(entry, 'published', stream_entry.created_at.iso8601) | ||||||
|  |     append_element(entry, 'updated', stream_entry.updated_at.iso8601) | ||||||
|  |     append_element(entry, 'title', stream_entry&.status&.title) | ||||||
|  | 
 | ||||||
|  |     entry << author(stream_entry.account) if root | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[stream_entry.object_type]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[stream_entry.verb]) | ||||||
|  | 
 | ||||||
|  |     entry << object(stream_entry.target) if stream_entry.targeted? | ||||||
|  | 
 | ||||||
|  |     serialize_status_attributes(entry, stream_entry.status) unless stream_entry.status.nil? | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: account_stream_entry_url(stream_entry.account, stream_entry)) | ||||||
|  |     append_element(entry, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom')) | ||||||
|  |     append_element(entry, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(stream_entry.thread), href: TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded? | ||||||
|  | 
 | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def object(status) | ||||||
|  |     object = Ox::Element.new('activity:object') | ||||||
|  | 
 | ||||||
|  |     append_element(object, 'id', TagManager.instance.uri_for(status)) | ||||||
|  |     append_element(object, 'published', status.created_at.iso8601) | ||||||
|  |     append_element(object, 'updated', status.updated_at.iso8601) | ||||||
|  |     append_element(object, 'title', status.title) | ||||||
|  | 
 | ||||||
|  |     object << author(status.account) | ||||||
|  | 
 | ||||||
|  |     append_element(object, 'activity:object-type', TagManager::TYPES[status.object_type]) | ||||||
|  |     append_element(object, 'activity:verb', TagManager::VERBS[status.verb]) | ||||||
|  | 
 | ||||||
|  |     serialize_status_attributes(object, status) | ||||||
|  | 
 | ||||||
|  |     append_element(object, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(status)) | ||||||
|  |     append_element(object, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(status.thread), href: TagManager.instance.url_for(status.thread)) if status.reply? | ||||||
|  | 
 | ||||||
|  |     object | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def follow_salmon(follow) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     description = "#{follow.account.acct} started following #{follow.target_account.acct}" | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(follow.created_at, follow.id, 'Follow')) | ||||||
|  |     append_element(entry, 'title', description) | ||||||
|  |     append_element(entry, 'content', description, type: :html) | ||||||
|  | 
 | ||||||
|  |     entry << author(follow.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:follow]) | ||||||
|  | 
 | ||||||
|  |     object = author(follow.target_account) | ||||||
|  |     object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     entry << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def follow_request_salmon(follow_request) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(follow_request.created_at, follow_request.id, 'FollowRequest')) | ||||||
|  |     append_element(entry, 'title', "#{follow_request.account.acct} requested to follow #{follow_request.target_account.acct}") | ||||||
|  | 
 | ||||||
|  |     entry << author(follow_request.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:request_friend]) | ||||||
|  | 
 | ||||||
|  |     object = author(follow_request.target_account) | ||||||
|  |     object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     entry << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def authorize_follow_request_salmon(follow_request) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(Time.now.utc, follow_request.id, 'FollowRequest')) | ||||||
|  |     append_element(entry, 'title', "#{follow_request.target_account.acct} authorizes follow request by #{follow_request.account.acct}") | ||||||
|  | 
 | ||||||
|  |     entry << author(follow_request.target_account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:authorize]) | ||||||
|  | 
 | ||||||
|  |     object = Ox::Element.new('activity:object') | ||||||
|  |     object << author(follow_request.account) | ||||||
|  | 
 | ||||||
|  |     append_element(object, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(object, 'activity:verb', TagManager::VERBS[:request_friend]) | ||||||
|  | 
 | ||||||
|  |     inner_object = author(follow_request.target_account) | ||||||
|  |     inner_object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     object << inner_object | ||||||
|  |     entry  << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def reject_follow_request_salmon(follow_request) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(Time.now.utc, follow_request.id, 'FollowRequest')) | ||||||
|  |     append_element(entry, 'title', "#{follow_request.target_account.acct} rejects follow request by #{follow_request.account.acct}") | ||||||
|  | 
 | ||||||
|  |     entry << author(follow_request.target_account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:reject]) | ||||||
|  | 
 | ||||||
|  |     object = Ox::Element.new('activity:object') | ||||||
|  |     object << author(follow_request.account) | ||||||
|  | 
 | ||||||
|  |     append_element(object, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(object, 'activity:verb', TagManager::VERBS[:request_friend]) | ||||||
|  | 
 | ||||||
|  |     inner_object = author(follow_request.target_account) | ||||||
|  |     inner_object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     object << inner_object | ||||||
|  |     entry  << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def unfollow_salmon(follow) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     description = "#{follow.account.acct} is no longer following #{follow.target_account.acct}" | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(Time.now.utc, follow.id, 'Follow')) | ||||||
|  |     append_element(entry, 'title', description) | ||||||
|  |     append_element(entry, 'content', description, type: :html) | ||||||
|  | 
 | ||||||
|  |     entry << author(follow.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:unfollow]) | ||||||
|  | 
 | ||||||
|  |     object = author(follow.target_account) | ||||||
|  |     object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     entry << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def block_salmon(block) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     description = "#{block.account.acct} no longer wishes to interact with #{block.target_account.acct}" | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(Time.now.utc, block.id, 'Block')) | ||||||
|  |     append_element(entry, 'title', description) | ||||||
|  | 
 | ||||||
|  |     entry << author(block.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:block]) | ||||||
|  | 
 | ||||||
|  |     object = author(block.target_account) | ||||||
|  |     object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     entry << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def unblock_salmon(block) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     description = "#{block.account.acct} no longer blocks #{block.target_account.acct}" | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(Time.now.utc, block.id, 'Block')) | ||||||
|  |     append_element(entry, 'title', description) | ||||||
|  | 
 | ||||||
|  |     entry << author(block.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:unblock]) | ||||||
|  | 
 | ||||||
|  |     object = author(block.target_account) | ||||||
|  |     object.value = 'activity:object' | ||||||
|  | 
 | ||||||
|  |     entry << object | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def favourite_salmon(favourite) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     description = "#{favourite.account.acct} favourited a status by #{favourite.status.account.acct}" | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(favourite.created_at, favourite.id, 'Favourite')) | ||||||
|  |     append_element(entry, 'title', description) | ||||||
|  |     append_element(entry, 'content', description, type: :html) | ||||||
|  | 
 | ||||||
|  |     entry << author(favourite.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:favorite]) | ||||||
|  | 
 | ||||||
|  |     entry << object(favourite.status) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(favourite.status), href: TagManager.instance.url_for(favourite.status)) | ||||||
|  | 
 | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def unfavourite_salmon(favourite) | ||||||
|  |     entry = Ox::Element.new('entry') | ||||||
|  |     add_namespaces(entry) | ||||||
|  | 
 | ||||||
|  |     description = "#{favourite.account.acct} no longer favourites a status by #{favourite.status.account.acct}" | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'id', TagManager.instance.unique_tag(Time.now.utc, favourite.id, 'Favourite')) | ||||||
|  |     append_element(entry, 'title', description) | ||||||
|  |     append_element(entry, 'content', description, type: :html) | ||||||
|  | 
 | ||||||
|  |     entry << author(favourite.account) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'activity:object-type', TagManager::TYPES[:activity]) | ||||||
|  |     append_element(entry, 'activity:verb', TagManager::VERBS[:unfavorite]) | ||||||
|  | 
 | ||||||
|  |     entry << object(favourite.status) | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(favourite.status), href: TagManager.instance.url_for(favourite.status)) | ||||||
|  | 
 | ||||||
|  |     entry | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def append_element(parent, name, content = nil, attributes = {}) | ||||||
|  |     element = Ox::Element.new(name) | ||||||
|  |     attributes.each { |k, v| element[k] = v.to_s } | ||||||
|  |     element << content.to_s unless content.nil? | ||||||
|  |     parent  << element | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def add_namespaces(parent) | ||||||
|  |     parent['xmlns']          = TagManager::XMLNS | ||||||
|  |     parent['xmlns:thr']      = TagManager::THR_XMLNS | ||||||
|  |     parent['xmlns:activity'] = TagManager::AS_XMLNS | ||||||
|  |     parent['xmlns:poco']     = TagManager::POCO_XMLNS | ||||||
|  |     parent['xmlns:media']    = TagManager::MEDIA_XMLNS | ||||||
|  |     parent['xmlns:ostatus']  = TagManager::OS_XMLNS | ||||||
|  |     parent['xmlns:mastodon'] = TagManager::MTDN_XMLNS | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def serialize_status_attributes(entry, status) | ||||||
|  |     append_element(entry, 'summary', status.spoiler_text) unless status.spoiler_text.blank? | ||||||
|  |     append_element(entry, 'content', Formatter.instance.format(status.reblog? ? status.reblog : status).to_str, type: 'html') | ||||||
|  | 
 | ||||||
|  |     status.mentions.each do |mentioned| | ||||||
|  |       append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': TagManager::TYPES[:person], href: TagManager.instance.uri_for(mentioned.account)) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': TagManager::TYPES[:collection], href: TagManager::COLLECTIONS[:public]) if status.public_visibility? | ||||||
|  | 
 | ||||||
|  |     status.tags.each do |tag| | ||||||
|  |       append_element(entry, 'category', nil, term: tag.name) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'category', nil, term: 'nsfw') if status.sensitive? | ||||||
|  | 
 | ||||||
|  |     status.media_attachments.each do |media| | ||||||
|  |       append_element(entry, 'link', nil, rel: :enclosure, type: media.file_content_type, length: media.file_file_size, href: full_asset_url(media.file.url(:original, false))) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     append_element(entry, 'mastodon:scope', status.visibility) | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -78,6 +78,8 @@ class TagManager | ||||||
|     case target.object_type |     case target.object_type | ||||||
|     when :person |     when :person | ||||||
|       account_url(target) |       account_url(target) | ||||||
|  |     when :note, :comment, :activity | ||||||
|  |       unique_tag(target.created_at, target.id, 'Status') | ||||||
|     else |     else | ||||||
|       unique_tag(target.stream_entry.created_at, target.stream_entry.activity_id, target.stream_entry.activity_type) |       unique_tag(target.stream_entry.created_at, target.stream_entry.activity_id, target.stream_entry.activity_type) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  | @ -5,25 +5,21 @@ class StreamEntry < ApplicationRecord | ||||||
| 
 | 
 | ||||||
|   belongs_to :account, inverse_of: :stream_entries |   belongs_to :account, inverse_of: :stream_entries | ||||||
|   belongs_to :activity, polymorphic: true |   belongs_to :activity, polymorphic: true | ||||||
| 
 |  | ||||||
|   belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', inverse_of: :stream_entry |   belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', inverse_of: :stream_entry | ||||||
| 
 | 
 | ||||||
|   validates :account, :activity, presence: true |   validates :account, :activity, presence: true | ||||||
| 
 | 
 | ||||||
|   STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, mentions: :account], thread: [:stream_entry, :account]].freeze |   STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :media_attachments, :tags, mentions: :account], thread: [:stream_entry, :account]].freeze | ||||||
| 
 | 
 | ||||||
|  |   default_scope { where(activity_type: 'Status') } | ||||||
|   scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) } |   scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) } | ||||||
| 
 | 
 | ||||||
|   def object_type |   def object_type | ||||||
|     if orphaned? |     orphaned? || targeted? ? :activity : status.object_type | ||||||
|       :activity |  | ||||||
|     else |  | ||||||
|       targeted? ? :activity : activity.object_type |  | ||||||
|     end |  | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def verb |   def verb | ||||||
|     orphaned? ? :delete : activity.verb |     orphaned? ? :delete : status.verb | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def targeted? |   def targeted? | ||||||
|  | @ -31,15 +27,15 @@ class StreamEntry < ApplicationRecord | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def target |   def target | ||||||
|     orphaned? ? nil : activity.target |     orphaned? ? nil : status.target | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def title |   def title | ||||||
|     orphaned? ? nil : activity.title |     orphaned? ? nil : status.title | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def content |   def content | ||||||
|     orphaned? ? nil : activity.content |     orphaned? ? nil : status.content | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def threaded? |   def threaded? | ||||||
|  | @ -47,20 +43,16 @@ class StreamEntry < ApplicationRecord | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def thread |   def thread | ||||||
|     orphaned? ? nil : activity.thread |     orphaned? ? nil : status.thread | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def mentions |   def mentions | ||||||
|     activity.respond_to?(:mentions) ? activity.mentions.map(&:account) : [] |     orphaned? ? [] : status.mentions.map(&:account) | ||||||
|   end |  | ||||||
| 
 |  | ||||||
|   def activity |  | ||||||
|     !new_record? ? send(activity_type.underscore) || super : super |  | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def orphaned? |   def orphaned? | ||||||
|     activity.nil? |     status.nil? | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -9,20 +9,20 @@ class AfterBlockService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def clear_timelines(account, target_account) |   def clear_timelines(account, target_account) | ||||||
|     mentions_key = FeedManager.instance.key(:mentions, account.id) |  | ||||||
|     home_key = FeedManager.instance.key(:home, account.id) |     home_key = FeedManager.instance.key(:home, account.id) | ||||||
| 
 | 
 | ||||||
|  |     redis.pipelined do | ||||||
|       target_account.statuses.select('id').find_each do |status| |       target_account.statuses.select('id').find_each do |status| | ||||||
|       redis.zrem(mentions_key, status.id) |  | ||||||
|         redis.zrem(home_key, status.id) |         redis.zrem(home_key, status.id) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  |   end | ||||||
| 
 | 
 | ||||||
|   def clear_notifications(account, target_account) |   def clear_notifications(account, target_account) | ||||||
|     Notification.where(account: account).joins(:follow).where(activity_type: 'Follow', follows: { account_id: target_account.id }).destroy_all |     Notification.where(account: account).joins(:follow).where(activity_type: 'Follow', follows: { account_id: target_account.id }).delete_all | ||||||
|     Notification.where(account: account).joins(mention: :status).where(activity_type: 'Mention', statuses: { account_id: target_account.id }).destroy_all |     Notification.where(account: account).joins(mention: :status).where(activity_type: 'Mention', statuses: { account_id: target_account.id }).delete_all | ||||||
|     Notification.where(account: account).joins(:favourite).where(activity_type: 'Favourite', favourites: { account_id: target_account.id }).destroy_all |     Notification.where(account: account).joins(:favourite).where(activity_type: 'Favourite', favourites: { account_id: target_account.id }).delete_all | ||||||
|     Notification.where(account: account).joins(:status).where(activity_type: 'Status', statuses: { account_id: target_account.id }).destroy_all |     Notification.where(account: account).joins(:status).where(activity_type: 'Status', statuses: { account_id: target_account.id }).delete_all | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def redis |   def redis | ||||||
|  |  | ||||||
|  | @ -10,31 +10,6 @@ class AuthorizeFollowService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(follow_request) |   def build_xml(follow_request) | ||||||
|     Nokogiri::XML::Builder.new do |xml| |     AtomSerializer.render(AtomSerializer.new.authorize_follow_request_salmon(follow_request)) | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, Time.now.utc, follow_request.id, 'FollowRequest' |  | ||||||
|         title xml, "#{follow_request.target_account.acct} authorizes follow request by #{follow_request.account.acct}" |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, follow_request.target_account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :authorize |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           author(xml) do |  | ||||||
|             include_author xml, follow_request.account |  | ||||||
|           end |  | ||||||
| 
 |  | ||||||
|           object_type xml, :activity |  | ||||||
|           verb xml, :request_friend |  | ||||||
| 
 |  | ||||||
|           target(xml) do |  | ||||||
|             include_author xml, follow_request.target_account |  | ||||||
|           end |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -18,22 +18,6 @@ class BlockService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(block) |   def build_xml(block) | ||||||
|     Nokogiri::XML::Builder.new do |xml| |     AtomSerializer.render(AtomSerializer.new.block_salmon(block)) | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, block.created_at, block.id, 'Block' |  | ||||||
|         title xml, "#{block.account.acct} no longer wishes to interact with #{block.target_account.acct}" |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, block.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :block |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_author xml, block.target_account |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ | ||||||
| 
 | 
 | ||||||
| module StreamEntryRenderer | module StreamEntryRenderer | ||||||
|   def stream_entry_to_xml(stream_entry) |   def stream_entry_to_xml(stream_entry) | ||||||
|     renderer = StreamEntriesController.renderer.new(method: 'get', http_host: Rails.configuration.x.local_domain, https: Rails.configuration.x.use_https) |     AtomSerializer.render(AtomSerializer.new.entry(stream_entry, true)) | ||||||
|     renderer.render(:show, assigns: { stream_entry: stream_entry }, formats: [:atom]) |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -22,26 +22,6 @@ class FavouriteService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(favourite) |   def build_xml(favourite) | ||||||
|     description = "#{favourite.account.acct} favourited a status by #{favourite.status.account.acct}" |     AtomSerializer.render(AtomSerializer.new.favourite_salmon(favourite)) | ||||||
| 
 |  | ||||||
|     Nokogiri::XML::Builder.new do |xml| |  | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, favourite.created_at, favourite.id, 'Favourite' |  | ||||||
|         title xml, description |  | ||||||
|         content xml, description |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, favourite.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :favorite |  | ||||||
|         in_reply_to xml, TagManager.instance.uri_for(favourite.status), TagManager.instance.url_for(favourite.status) |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_target xml, favourite.status |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -55,48 +55,10 @@ class FollowService < BaseService | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def build_follow_request_xml(follow_request) |   def build_follow_request_xml(follow_request) | ||||||
|     description = "#{follow_request.account.acct} requested to follow #{follow_request.target_account.acct}" |     AtomSerializer.render(AtomSerializer.new.follow_request_salmon(follow_request)) | ||||||
| 
 |  | ||||||
|     Nokogiri::XML::Builder.new do |xml| |  | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, follow_request.created_at, follow_request.id, 'FollowRequest' |  | ||||||
|         title xml, description |  | ||||||
|         content xml, description |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, follow_request.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :request_friend |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_author xml, follow_request.target_account |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def build_follow_xml(follow) |   def build_follow_xml(follow) | ||||||
|     description = "#{follow.account.acct} started following #{follow.target_account.acct}" |     AtomSerializer.render(AtomSerializer.new.follow_salmon(follow)) | ||||||
| 
 |  | ||||||
|     Nokogiri::XML::Builder.new do |xml| |  | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, follow.created_at, follow.id, 'Follow' |  | ||||||
|         title xml, description |  | ||||||
|         content xml, description |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, follow.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :follow |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_author xml, follow.target_account |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -10,31 +10,6 @@ class RejectFollowService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(follow_request) |   def build_xml(follow_request) | ||||||
|     Nokogiri::XML::Builder.new do |xml| |     AtomSerializer.render(AtomSerializer.new.reject_follow_request_salmon(follow_request)) | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, Time.now.utc, follow_request.id, 'FollowRequest' |  | ||||||
|         title xml, "#{follow_request.target_account.acct} rejects follow request by #{follow_request.account.acct}" |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, follow_request.target_account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :reject |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           author(xml) do |  | ||||||
|             include_author xml, follow_request.account |  | ||||||
|           end |  | ||||||
| 
 |  | ||||||
|           object_type xml, :activity |  | ||||||
|           verb xml, :request_friend |  | ||||||
| 
 |  | ||||||
|           target(xml) do |  | ||||||
|             include_author xml, follow_request.target_account |  | ||||||
|           end |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -11,22 +11,6 @@ class UnblockService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(block) |   def build_xml(block) | ||||||
|     Nokogiri::XML::Builder.new do |xml| |     AtomSerializer.render(AtomSerializer.new.unblock_salmon(block)) | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, Time.now.utc, block.id, 'Block' |  | ||||||
|         title xml, "#{block.account.acct} no longer blocks #{block.target_account.acct}" |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, block.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :unblock |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_author xml, block.target_account |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -13,26 +13,6 @@ class UnfavouriteService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(favourite) |   def build_xml(favourite) | ||||||
|     description = "#{favourite.account.acct} no longer favourites a status by #{favourite.status.account.acct}" |     AtomSerializer.render(AtomSerializer.new.unfavourite_salmon(favourite)) | ||||||
| 
 |  | ||||||
|     Nokogiri::XML::Builder.new do |xml| |  | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, Time.now.utc, favourite.id, 'Favourite' |  | ||||||
|         title xml, description |  | ||||||
|         content xml, description |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, favourite.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :unfavorite |  | ||||||
|         in_reply_to xml, TagManager.instance.uri_for(favourite.status), TagManager.instance.url_for(favourite.status) |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_target xml, favourite.status |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -13,25 +13,6 @@ class UnfollowService < BaseService | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def build_xml(follow) |   def build_xml(follow) | ||||||
|     description = "#{follow.account.acct} is no longer following #{follow.target_account.acct}" |     AtomSerializer.render(AtomSerializer.new.unfollow_salmon(follow)) | ||||||
| 
 |  | ||||||
|     Nokogiri::XML::Builder.new do |xml| |  | ||||||
|       entry(xml, true) do |  | ||||||
|         unique_id xml, Time.now.utc, follow.id, 'Follow' |  | ||||||
|         title xml, description |  | ||||||
|         content xml, description |  | ||||||
| 
 |  | ||||||
|         author(xml) do |  | ||||||
|           include_author xml, follow.account |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         object_type xml, :activity |  | ||||||
|         verb xml, :unfollow |  | ||||||
| 
 |  | ||||||
|         target(xml) do |  | ||||||
|           include_author xml, follow.target_account |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end.to_xml |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| Nokogiri::XML::Builder.new do |xml| |  | ||||||
|   feed(xml) do |  | ||||||
|     simple_id  xml, account_url(@account, format: 'atom') |  | ||||||
|     title      xml, @account.display_name |  | ||||||
|     subtitle   xml, @account.note |  | ||||||
|     updated_at xml, stream_updated_at |  | ||||||
|     logo       xml, full_asset_url(@account.avatar.url(:original)) |  | ||||||
| 
 |  | ||||||
|     author(xml) do |  | ||||||
|       include_author xml, @account |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     link_alternate xml, TagManager.instance.url_for(@account) |  | ||||||
|     link_self      xml, account_url(@account, format: 'atom') |  | ||||||
|     link_next      xml, account_url(@account, format: 'atom', max_id: @entries.last.id) if @entries.size == 20 |  | ||||||
|     link_hub       xml, api_push_url |  | ||||||
|     link_salmon    xml, api_salmon_url(@account.id) |  | ||||||
| 
 |  | ||||||
|     @entries.each do |stream_entry| |  | ||||||
|       entry(xml, false) do |  | ||||||
|         include_entry xml, stream_entry |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| end.to_xml |  | ||||||
|  | @ -11,8 +11,10 @@ | ||||||
|     %meta{:name => "theme-color", :content => "#282c37"}/ |     %meta{:name => "theme-color", :content => "#282c37"}/ | ||||||
|     %meta{:name => "apple-mobile-web-app-capable", :content => "yes"}/ |     %meta{:name => "apple-mobile-web-app-capable", :content => "yes"}/ | ||||||
| 
 | 
 | ||||||
|     %title |     %title< | ||||||
|       = "#{yield(:page_title)} - " if content_for?(:page_title) |       - if content_for?(:page_title) | ||||||
|  |         = yield(:page_title) | ||||||
|  |         = ' - ' | ||||||
|       = Setting.site_title |       = Setting.site_title | ||||||
| 
 | 
 | ||||||
|     = stylesheet_link_tag 'application', media: 'all' |     = stylesheet_link_tag 'application', media: 'all' | ||||||
|  |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| Nokogiri::XML::Builder.new do |xml| |  | ||||||
|   entry(xml, true) do |  | ||||||
|     author(xml) do |  | ||||||
|       include_author xml, @stream_entry.account |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     include_entry xml, @stream_entry |  | ||||||
|   end |  | ||||||
| end.to_xml |  | ||||||
|  | @ -13,6 +13,9 @@ class Pubsubhubbub::DeliveryWorker | ||||||
|   def perform(subscription_id, payload) |   def perform(subscription_id, payload) | ||||||
|     subscription = Subscription.find(subscription_id) |     subscription = Subscription.find(subscription_id) | ||||||
|     headers      = {} |     headers      = {} | ||||||
|  |     host         = Addressable::URI.parse(subscription.callback_url).host | ||||||
|  | 
 | ||||||
|  |     return if DomainBlock.blocked?(host) | ||||||
| 
 | 
 | ||||||
|     headers['User-Agent']      = 'Mastodon/PubSubHubbub' |     headers['User-Agent']      = 'Mastodon/PubSubHubbub' | ||||||
|     headers['Link']            = LinkHeader.new([[api_push_url, [%w(rel hub)]], [account_url(subscription.account, format: :atom), [%w(rel self)]]]).to_s |     headers['Link']            = LinkHeader.new([[api_push_url, [%w(rel hub)]], [account_url(subscription.account, format: :atom), [%w(rel self)]]]).to_s | ||||||
|  |  | ||||||
|  | @ -11,13 +11,9 @@ class Pubsubhubbub::DistributionWorker | ||||||
|     return if stream_entry.hidden? |     return if stream_entry.hidden? | ||||||
| 
 | 
 | ||||||
|     account = stream_entry.account |     account = stream_entry.account | ||||||
|     renderer = AccountsController.renderer.new(method: 'get', http_host: Rails.configuration.x.local_domain, https: Rails.configuration.x.use_https) |     payload = AtomSerializer.render(AtomSerializer.new.feed(account, [stream_entry])) | ||||||
|     payload  = renderer.render(:show, assigns: { account: account, entries: [stream_entry] }, formats: [:atom]) |  | ||||||
|     # 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| | ||||||
|       host = Addressable::URI.parse(subscription.callback_url).host |  | ||||||
|       next if DomainBlock.blocked?(host) # || !domains.include?(host) |  | ||||||
|       Pubsubhubbub::DeliveryWorker.perform_async(subscription.id, payload) |       Pubsubhubbub::DeliveryWorker.perform_async(subscription.id, payload) | ||||||
|     end |     end | ||||||
|   rescue ActiveRecord::RecordNotFound |   rescue ActiveRecord::RecordNotFound | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ preload_app! | ||||||
| 
 | 
 | ||||||
| on_worker_boot do | on_worker_boot do | ||||||
|   if ENV['HEROKU'] # Spawn the workers from Puma, to only use one dyno |   if ENV['HEROKU'] # Spawn the workers from Puma, to only use one dyno | ||||||
|     @sidekiq_pid ||= spawn('bundle exec sidekiq -q default -q mailers -q push') |     @sidekiq_pid ||= spawn('bundle exec sidekiq -q default -q push -q pull -q mailers ') | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   ActiveRecord::Base.establish_connection if defined?(ActiveRecord) |   ActiveRecord::Base.establish_connection if defined?(ActiveRecord) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | class AddNotificationsAndFavouritesIndices < ActiveRecord::Migration[5.0] | ||||||
|  |   def change | ||||||
|  |     add_index :notifications, [:activity_id, :activity_type] | ||||||
|  |     add_index :accounts, :url | ||||||
|  |     add_index :favourites, :status_id | ||||||
|  |   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: 20170405112956) do | ActiveRecord::Schema.define(version: 20170406215816) 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" | ||||||
|  | @ -49,6 +49,7 @@ ActiveRecord::Schema.define(version: 20170405112956) do | ||||||
|     t.integer  "following_count",         default: 0,     null: false |     t.integer  "following_count",         default: 0,     null: false | ||||||
|     t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin |     t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin | ||||||
|     t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower", using: :btree |     t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower", using: :btree | ||||||
|  |     t.index ["url"], name: "index_accounts_on_url", using: :btree | ||||||
|     t.index ["username", "domain"], name: "index_accounts_on_username_and_domain", unique: true, using: :btree |     t.index ["username", "domain"], name: "index_accounts_on_username_and_domain", unique: true, using: :btree | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  | @ -75,6 +76,7 @@ ActiveRecord::Schema.define(version: 20170405112956) do | ||||||
|     t.datetime "created_at", null: false |     t.datetime "created_at", null: false | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id", "status_id"], name: "index_favourites_on_account_id_and_status_id", unique: true, using: :btree |     t.index ["account_id", "status_id"], name: "index_favourites_on_account_id_and_status_id", unique: true, using: :btree | ||||||
|  |     t.index ["status_id"], name: "index_favourites_on_status_id", using: :btree | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   create_table "follow_requests", force: :cascade do |t| |   create_table "follow_requests", force: :cascade do |t| | ||||||
|  | @ -128,6 +130,7 @@ ActiveRecord::Schema.define(version: 20170405112956) do | ||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", null: false | ||||||
|     t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree |     t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree | ||||||
|     t.index ["status_id"], name: "index_mentions_on_status_id", using: :btree |     t.index ["status_id"], name: "index_mentions_on_status_id", using: :btree | ||||||
|  |     t.index ["status_id"], name: "mentions_status_id_index", using: :btree | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   create_table "mutes", force: :cascade do |t| |   create_table "mutes", force: :cascade do |t| | ||||||
|  | @ -146,6 +149,7 @@ ActiveRecord::Schema.define(version: 20170405112956) do | ||||||
|     t.datetime "updated_at",      null: false |     t.datetime "updated_at",      null: false | ||||||
|     t.integer  "from_account_id" |     t.integer  "from_account_id" | ||||||
|     t.index ["account_id", "activity_id", "activity_type"], name: "account_activity", unique: true, using: :btree |     t.index ["account_id", "activity_id", "activity_type"], name: "account_activity", unique: true, using: :btree | ||||||
|  |     t.index ["activity_id", "activity_type"], name: "index_notifications_on_activity_id_and_activity_type", using: :btree | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   create_table "oauth_access_grants", force: :cascade do |t| |   create_table "oauth_access_grants", force: :cascade do |t| | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue