Improve ActivityPub representations (#3844)
* Improve webfinger templates and make tests more flexible * Clean up AS2 representation of actor * Refactor outbox * Create activities representation * Add representations of followers/following collections, do not redirect /users/:username route if format is empty * Remove unused translations * ActivityPub endpoint for single statuses, add ActivityPub::TagManager for better URL/URI generation * Add ActivityPub::TagManager#to * Represent all attachments as Document instead of Image/Video specifically (Because for remote ones we may not know for sure) Add mentions and hashtags representation to AP notes * Add AP-resolvable hashtag URIs * Use ActiveModelSerializers for ActivityPub * Clean up unused translations * Separate route for object and activity * Adjust cc/to matrices * Add to/cc to activities, ensure announce activity embeds target status and not the wrapper status, add "id" to all collections
This commit is contained in:
		
					parent
					
						
							
								3fbf1bf35a
							
						
					
				
			
			
				commit
				
					
						8c45cd0e36
					
				
			
		
					 61 changed files with 443 additions and 725 deletions
				
			
		
							
								
								
									
										13
									
								
								app/lib/activitypub/adapter.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/lib/activitypub/adapter.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base | ||||
|   def self.default_key_transform | ||||
|     :camel_lower | ||||
|   end | ||||
| 
 | ||||
|   def serializable_hash(options = nil) | ||||
|     options = serialization_options(options) | ||||
|     serialized_hash = { '@context': 'https://www.w3.org/ns/activitystreams' }.merge(ActiveModelSerializers::Adapter::Attributes.new(serializer, instance_options).serializable_hash(options)) | ||||
|     self.class.transform_key_casing!(serialized_hash, instance_options) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										69
									
								
								app/lib/activitypub/tag_manager.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								app/lib/activitypub/tag_manager.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| require 'singleton' | ||||
| 
 | ||||
| class ActivityPub::TagManager | ||||
|   include Singleton | ||||
|   include RoutingHelper | ||||
| 
 | ||||
|   COLLECTIONS = { | ||||
|     public: 'https://www.w3.org/ns/activitystreams#Public', | ||||
|   }.freeze | ||||
| 
 | ||||
|   def url_for(target) | ||||
|     return target.url if target.respond_to?(:local?) && !target.local? | ||||
| 
 | ||||
|     case target.object_type | ||||
|     when :person | ||||
|       short_account_url(target) | ||||
|     when :note, :comment, :activity | ||||
|       short_account_status_url(target.account, target) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def uri_for(target) | ||||
|     return target.uri if target.respond_to?(:local?) && !target.local? | ||||
| 
 | ||||
|     case target.object_type | ||||
|     when :person | ||||
|       account_url(target) | ||||
|     when :note, :comment, :activity | ||||
|       account_status_url(target.account, target) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   # Primary audience of a status | ||||
|   # Public statuses go out to primarily the public collection | ||||
|   # Unlisted and private statuses go out primarily to the followers collection | ||||
|   # Others go out only to the people they mention | ||||
|   def to(status) | ||||
|     case status.visibility | ||||
|     when 'public' | ||||
|       [COLLECTIONS[:public]] | ||||
|     when 'unlisted', 'private' | ||||
|       [account_followers_url(status.account)] | ||||
|     when 'direct' | ||||
|       status.mentions.map { |mention| uri_for(mention.account) } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   # Secondary audience of a status | ||||
|   # Public statuses go out to followers as well | ||||
|   # Unlisted statuses go to the public as well | ||||
|   # Both of those and private statuses also go to the people mentioned in them | ||||
|   # Direct ones don't have a secondary audience | ||||
|   def cc(status) | ||||
|     cc = [] | ||||
| 
 | ||||
|     case status.visibility | ||||
|     when 'public' | ||||
|       cc << account_followers_url(status.account) | ||||
|     when 'unlisted' | ||||
|       cc << COLLECTIONS[:public] | ||||
|     end | ||||
| 
 | ||||
|     cc.concat(status.mentions.map { |mention| uri_for(mention.account) }) unless status.direct_visibility? | ||||
| 
 | ||||
|     cc | ||||
|   end | ||||
| end | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue