2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/ *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   GoToSocial 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   Copyright  ( C )  2021  GoToSocial  Authors  admin @ gotosocial . org 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   This  program  is  free  software :  you  can  redistribute  it  and / or  modify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   it  under  the  terms  of  the  GNU  Affero  General  Public  License  as  published  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   the  Free  Software  Foundation ,  either  version  3  of  the  License ,  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   ( at  your  option )  any  later  version . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   This  program  is  distributed  in  the  hope  that  it  will  be  useful , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   but  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .   See  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   GNU  Affero  General  Public  License  for  more  details . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   You  should  have  received  a  copy  of  the  GNU  Affero  General  Public  License 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   along  with  this  program .   If  not ,  see  < http : //www.gnu.org/licenses/>. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* /  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  message  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2021-05-15 11:58:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-15 11:58:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/sirupsen/logrus" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									apimodel  "github.com/superseriousbusiness/gotosocial/internal/api/model" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/config" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/db" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/federation" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/media" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/oauth" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/storage" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/typeutils" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Processor should be passed to api modules (see internal/apimodule/...). It is used for  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// passing messages back and forth from the client API and the federating interface, via channels.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// It also contains logic for filtering which messages should end up where.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// It is designed to be used asynchronously: the client API and the federating API should just be able to  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// fire messages into the processor and not wait for a reply before proceeding with other work. This allows  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// for clean distribution of messages without slowing down the client API and harming the user experience.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Processor  interface  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ToClientAPI returns a channel for putting in messages that need to go to the gts client API. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ToClientAPI ( )  chan  ToClientAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// FromClientAPI returns a channel for putting messages in that come from the client api going to the processor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									FromClientAPI ( )  chan  FromClientAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ToFederator returns a channel for putting in messages that need to go to the federator (activitypub). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ToFederator ( )  chan  ToFederator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// FromFederator returns a channel for putting messages in that come from the federator (activitypub) going into the processor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									FromFederator ( )  chan  FromFederator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Start starts the Processor, reading from its channels and passing messages back and forth. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Start ( )  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Stop stops the processor cleanly, finishing handling any remaining messages before closing down. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Stop ( )  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/ * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CLIENT  API - FACING  PROCESSING  FUNCTIONS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										These  functions  are  intended  to  be  called  when  the  API  client  needs  an  immediate  ( ie . ,  synchronous )  reply 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										to  an  HTTP  request .  As  such ,  they  will  only  do  the  bare - minimum  of  work  necessary  to  give  a  properly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										formed  reply .  For  more  intensive  ( and  time - consuming )  calls ,  where  you  don ' t  require  an  immediate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										response ,  pass  work  to  the  processor  using  a  channel  instead . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// AccountCreate processes the given form for creating a new account, returning an oauth token for that account if successful. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AccountCreate ( authed  * oauth . Auth ,  form  * apimodel . AccountCreateRequest )  ( * apimodel . Token ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// AccountGet processes the given request for account information. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AccountGet ( authed  * oauth . Auth ,  targetAccountID  string )  ( * apimodel . Account ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// AccountUpdate processes the update of an account with the given form 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AccountUpdate ( authed  * oauth . Auth ,  form  * apimodel . UpdateCredentialsRequest )  ( * apimodel . Account ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-09 14:06:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// AdminEmojiCreate handles the creation of a new instance emoji by an admin, using the given form. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AdminEmojiCreate ( authed  * oauth . Auth ,  form  * apimodel . EmojiCreateRequest )  ( * apimodel . Emoji ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// AppCreate processes the creation of a new API application 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AppCreate ( authed  * oauth . Auth ,  form  * apimodel . ApplicationCreateRequest )  ( * apimodel . Application ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-10 16:29:05 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// FileGet handles the fetching of a media attachment file via the fileserver. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									FileGet ( authed  * oauth . Auth ,  form  * apimodel . GetContentRequestForm )  ( * apimodel . Content ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-15 11:58:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// FollowRequestsGet handles the getting of the authed account's incoming follow requests 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									FollowRequestsGet ( auth  * oauth . Auth )  ( [ ] apimodel . Account ,  ErrorWithCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// FollowRequestAccept handles the acceptance of a follow request from the given account ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									FollowRequestAccept ( auth  * oauth . Auth ,  accountID  string )  ErrorWithCode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-09 14:06:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// InstanceGet retrieves instance information for serving at api/v1/instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									InstanceGet ( domain  string )  ( * apimodel . Instance ,  ErrorWithCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// MediaCreate handles the creation of a media attachment, using the given form. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MediaCreate ( authed  * oauth . Auth ,  form  * apimodel . AttachmentRequest )  ( * apimodel . Attachment ,  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-10 16:29:05 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// MediaGet handles the GET of a media attachment with the given ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MediaGet ( authed  * oauth . Auth ,  attachmentID  string )  ( * apimodel . Attachment ,  ErrorWithCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// MediaUpdate handles the PUT of a media attachment with the given ID and form 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MediaUpdate ( authed  * oauth . Auth ,  attachmentID  string ,  form  * apimodel . AttachmentUpdateRequest )  ( * apimodel . Attachment ,  ErrorWithCode ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-09 14:06:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// StatusCreate processes the given form to create a new status, returning the api model representation of that status if it's OK. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusCreate ( authed  * oauth . Auth ,  form  * apimodel . AdvancedStatusCreateForm )  ( * apimodel . Status ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// StatusDelete processes the delete of a given status, returning the deleted status if the delete goes through. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusDelete ( authed  * oauth . Auth ,  targetStatusID  string )  ( * apimodel . Status ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// StatusFave processes the faving of a given status, returning the updated status if the fave goes through. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusFave ( authed  * oauth . Auth ,  targetStatusID  string )  ( * apimodel . Status ,  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 15:16:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// StatusBoost processes the boost/reblog of a given status, returning the newly-created boost if all is well. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusBoost ( authed  * oauth . Auth ,  targetStatusID  string )  ( * apimodel . Status ,  ErrorWithCode ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// StatusFavedBy returns a slice of accounts that have liked the given status, filtered according to privacy settings. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusFavedBy ( authed  * oauth . Auth ,  targetStatusID  string )  ( [ ] * apimodel . Account ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// StatusGet gets the given status, taking account of privacy settings and blocks etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusGet ( authed  * oauth . Auth ,  targetStatusID  string )  ( * apimodel . Status ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// StatusUnfave processes the unfaving of a given status, returning the updated status if the fave goes through. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									StatusUnfave ( authed  * oauth . Auth ,  targetStatusID  string )  ( * apimodel . Status ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/ * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										FEDERATION  API - FACING  PROCESSING  FUNCTIONS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										These  functions  are  intended  to  be  called  when  the  federating  client  needs  an  immediate  ( ie . ,  synchronous )  reply 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										to  an  HTTP  request .  As  such ,  they  will  only  do  the  bare - minimum  of  work  necessary  to  give  a  properly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										formed  reply .  For  more  intensive  ( and  time - consuming )  calls ,  where  you  don ' t  require  an  immediate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										response ,  pass  work  to  the  processor  using  a  channel  instead . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// GetFediUser handles the getting of a fedi/activitypub representation of a user/account, performing appropriate authentication 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// before returning a JSON serializable interface to the caller. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									GetFediUser ( requestedUsername  string ,  request  * http . Request )  ( interface { } ,  ErrorWithCode ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-09 20:34:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// GetWebfingerAccount handles the GET for a webfinger resource. Most commonly, it will be used for returning account lookups. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									GetWebfingerAccount ( requestedUsername  string ,  request  * http . Request )  ( * apimodel . WebfingerAccountResponse ,  ErrorWithCode ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-15 11:58:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// InboxPost handles POST requests to a user's inbox for new activitypub messages. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// InboxPost returns true if the request was handled as an ActivityPub POST to an actor's inbox. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If false, the request was not an ActivityPub request and may still be handled by the caller in another way, such as serving a web page. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If the error is nil, then the ResponseWriter's headers and response has already been written. If a non-nil error is returned, then no response has been written. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If the Actor was constructed with the Federated Protocol enabled, side effects will occur. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If the Federated Protocol is not enabled, writes the http.StatusMethodNotAllowed status code in the response. No side effects occur. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									InboxPost ( ctx  context . Context ,  w  http . ResponseWriter ,  r  * http . Request )  ( bool ,  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// processor just implements the Processor interface  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  processor  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// federator     pub.FederatingActor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									toClientAPI    chan  ToClientAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fromClientAPI  chan  FromClientAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									toFederator    chan  ToFederator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fromFederator  chan  FromFederator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									federator      federation . Federator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stop           chan  interface { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									log            * logrus . Logger 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									config         * config . Config 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tc             typeutils . TypeConverter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									oauthServer    oauth . Server 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mediaHandler   media . Handler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									storage        storage . Storage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									db             db . DB 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NewProcessor returns a new Processor that uses the given federator and logger  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  NewProcessor ( config  * config . Config ,  tc  typeutils . TypeConverter ,  federator  federation . Federator ,  oauthServer  oauth . Server ,  mediaHandler  media . Handler ,  storage  storage . Storage ,  db  db . DB ,  log  * logrus . Logger )  Processor  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & processor { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										toClientAPI :    make ( chan  ToClientAPI ,  100 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fromClientAPI :  make ( chan  FromClientAPI ,  100 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										toFederator :    make ( chan  ToFederator ,  100 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fromFederator :  make ( chan  FromFederator ,  100 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										federator :      federator , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										stop :           make ( chan  interface { } ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										log :            log , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										config :         config , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tc :             tc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										oauthServer :    oauthServer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mediaHandler :   mediaHandler , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										storage :        storage , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										db :             db , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  ToClientAPI ( )  chan  ToClientAPI  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  p . toClientAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  FromClientAPI ( )  chan  FromClientAPI  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  p . fromClientAPI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  ToFederator ( )  chan  ToFederator  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  p . toFederator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  FromFederator ( )  chan  FromFederator  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  p . fromFederator 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Start starts the Processor, reading from its channels and passing messages back and forth.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  Start ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									go  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									DistLoop : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  clientMsg  :=  <- p . toClientAPI : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												p . log . Infof ( "received message TO client API: %+v" ,  clientMsg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  clientMsg  :=  <- p . fromClientAPI : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												p . log . Infof ( "received message FROM client API: %+v" ,  clientMsg ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-15 11:58:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  err  :=  p . processFromClientAPI ( clientMsg ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													p . log . Error ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											case  federatorMsg  :=  <- p . toFederator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												p . log . Infof ( "received message TO federator: %+v" ,  federatorMsg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  federatorMsg  :=  <- p . fromFederator : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												p . log . Infof ( "received message FROM federator: %+v" ,  federatorMsg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  <- p . stop : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  DistLoop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Stop stops the processor cleanly, finishing handling any remaining messages before closing down.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// TODO: empty message buffer properly before stopping otherwise we'll lose federating messages.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  Stop ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									close ( p . stop ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ToClientAPI wraps a message that travels from the processor into the client API  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ToClientAPI  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APObjectType    gtsmodel . ActivityStreamsObject 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APActivityType  gtsmodel . ActivityStreamsActivity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Activity        interface { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// FromClientAPI wraps a message that travels from client API into the processor  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  FromClientAPI  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APObjectType    gtsmodel . ActivityStreamsObject 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APActivityType  gtsmodel . ActivityStreamsActivity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Activity        interface { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ToFederator wraps a message that travels from the processor into the federator  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ToFederator  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APObjectType    gtsmodel . ActivityStreamsObject 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APActivityType  gtsmodel . ActivityStreamsActivity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Activity        interface { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// FromFederator wraps a message that travels from the federator into the processor  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  FromFederator  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APObjectType    gtsmodel . ActivityStreamsObject 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									APActivityType  gtsmodel . ActivityStreamsActivity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Activity        interface { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-05-15 11:58:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  processFromClientAPI ( clientMsg  FromClientAPI )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  clientMsg . APObjectType  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  gtsmodel . ActivityStreamsNote : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status ,  ok  :=  clientMsg . Activity . ( * gtsmodel . Status ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  errors . New ( "note was not parseable as *gtsmodel.Status" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  p . notifyStatus ( status ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  status . VisibilityAdvanced . Federated  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  p . federateStatus ( status ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  fmt . Errorf ( "message type unprocessable: %+v" ,  clientMsg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  federateStatus ( status  * gtsmodel . Status )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// derive the sending account -- it might be attached to the status already 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sendingAcct  :=  & gtsmodel . Account { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  status . GTSAccount  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sendingAcct  =  status . GTSAccount 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// it wasn't attached so get it from the db instead 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  p . db . GetByID ( status . AccountID ,  sendingAcct ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									outboxURI ,  err  :=  url . Parse ( sendingAcct . OutboxURI ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// convert the status to AS format Note 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									note ,  err  :=  p . tc . StatusToAS ( status ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_ ,  err  =  p . federator . FederatingActor ( ) . Send ( context . Background ( ) ,  outboxURI ,  note ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * processor )  notifyStatus ( status  * gtsmodel . Status )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}