2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/ *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   GoToSocial 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   Copyright  ( C )  2021 - 2022  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  media  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"bytes" 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"codeberg.org/gruf/go-store/kv" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/db" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/uris" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ProcessingEmoji represents an emoji currently processing. It exposes  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// various functions for retrieving data from the process.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ProcessingEmoji  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mu  sync . Mutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:51:45 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// id of this instance's account -- pinned for convenience here so we only need to fetch it once 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									instanceAccountID  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/ * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										below  fields  should  be  set  on  newly  created  media ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										emoji  will  be  updated  incrementally  as  media  goes  through  processing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									emoji  * gtsmodel . Emoji 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									data   DataFunc 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									read   bool  // bool indicating that data function has been triggered already 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/ * 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										below  fields  represent  the  processing  state  of  the  static  of  the  emoji 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									* / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									staticState    processState 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									fullSizeState  processState 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/ * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										below  pointers  to  database  and  storage  are  maintained  so  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										the  media  can  store  and  update  itself  during  processing  steps 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									database  db . DB 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									storage   * kv . KVStore 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error  // error created during processing, if any 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 17:36:15 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// track whether this emoji has already been put in the databse 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									insertedInDB  bool 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// EmojiID returns the ID of the underlying emoji without blocking processing.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * ProcessingEmoji )  EmojiID ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  p . emoji . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// LoadEmoji blocks until the static and fullsize image  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// has been processed, and then returns the completed emoji.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * ProcessingEmoji )  LoadEmoji ( ctx  context . Context )  ( * gtsmodel . Emoji ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									p . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  p . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  p . store ( ctx ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  p . loadStatic ( ctx ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 17:36:15 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// store the result in the database before returning it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! p . insertedInDB  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  p . database . Put ( ctx ,  p . emoji ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . insertedInDB  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  p . emoji ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Finished returns true if processing has finished for both the thumbnail  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// and full fized version of this piece of media.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * ProcessingEmoji )  Finished ( )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  p . staticState  ==  complete  &&  p . fullSizeState  ==  complete 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( p  * ProcessingEmoji )  loadStatic ( ctx  context . Context )  error  {  
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									switch  p . staticState  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  received : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// stream the original file out of storage... 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										stored ,  err  :=  p . storage . GetStream ( p . emoji . ImagePath ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											p . err  =  fmt . Errorf ( "loadStatic: error fetching file from storage: %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											p . staticState  =  errored 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  p . err 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// we haven't processed a static version of this emoji yet so do it now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										static ,  err  :=  deriveStaticEmoji ( stored ,  p . emoji . ImageContentType ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p . err  =  fmt . Errorf ( "loadStatic: error deriving static: %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											p . staticState  =  errored 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  p . err 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  :=  stored . Close ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p . err  =  fmt . Errorf ( "loadStatic: error closing stored full size: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p . staticState  =  errored 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  p . err 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// put the static in storage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  p . storage . Put ( p . emoji . ImageStaticPath ,  static . small ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p . err  =  fmt . Errorf ( "loadStatic: error storing static: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p . staticState  =  errored 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  p . err 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										p . emoji . ImageStaticFileSize  =  len ( static . small ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// we're done processing the static version of the emoji! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p . staticState  =  complete 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										fallthrough 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  complete : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  errored : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  p . err 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  fmt . Errorf ( "static processing status %d unknown" ,  p . staticState ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// store calls the data function attached to p if it hasn't been called yet,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// and updates the underlying attachment fields as necessary. It will then stream  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// bytes from p's reader directly into storage so that it can be retrieved later.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( p  * ProcessingEmoji )  store ( ctx  context . Context )  error  {  
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// check if we've already done this and bail early if we have 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  p . read  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// execute the data function to get the reader out of it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reader ,  err  :=  p . data ( ctx ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Errorf ( "store: error executing data function: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// extract no more than 261 bytes from the beginning of the file -- this is the header 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									firstBytes  :=  make ( [ ] byte ,  maxFileHeaderBytes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  err  :=  reader . Read ( firstBytes ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "store: error reading initial %d bytes: %s" ,  maxFileHeaderBytes ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// now we have the file header we can work out the content type from it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									contentType ,  err  :=  parseContentType ( firstBytes ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Errorf ( "store: error parsing content type: %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// bail if this is a type we can't process 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ! supportedEmoji ( contentType )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  fmt . Errorf ( "store: content type %s was not valid for an emoji" ,  contentType ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// extract the file extension 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									split  :=  strings . Split ( contentType ,  "/" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									extension  :=  split [ 1 ]  // something like 'gif' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// set some additional fields on the emoji now that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we know more about what the underlying image actually is 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									p . emoji . ImageURL  =  uris . GenerateURIForAttachment ( p . instanceAccountID ,  string ( TypeEmoji ) ,  string ( SizeOriginal ) ,  p . emoji . ID ,  extension ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p . emoji . ImagePath  =  fmt . Sprintf ( "%s/%s/%s/%s.%s" ,  p . instanceAccountID ,  TypeEmoji ,  SizeOriginal ,  p . emoji . ID ,  extension ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p . emoji . ImageContentType  =  contentType 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-16 18:52:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// concatenate the first bytes with the existing bytes still in the reader (thanks Mara) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									multiReader  :=  io . MultiReader ( bytes . NewBuffer ( firstBytes ) ,  reader ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// store this for now -- other processes can pull it out of storage as they please 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  p . storage . PutStream ( p . emoji . ImagePath ,  multiReader ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "store: error storing stream: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p . emoji . ImageFileSize  =  36702  // TODO: set this based on the result of PutStream 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// if the original reader is a readcloser, close it since we're done with it now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  rc ,  ok  :=  reader . ( io . ReadCloser ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  rc . Close ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "store: error closing readcloser: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p . read  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * manager )  preProcessEmoji ( ctx  context . Context ,  data  DataFunc ,  shortcode  string ,  id  string ,  uri  string ,  ai  * AdditionalEmojiInfo )  ( * ProcessingEmoji ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									instanceAccount ,  err  :=  m . db . GetInstanceAccount ( ctx ,  "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "preProcessEmoji: error fetching this instance account from the db: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// populate initial fields on the emoji -- some of these will be overwritten as we proceed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									emoji  :=  & gtsmodel . Emoji { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ID :                      id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CreatedAt :               time . Now ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										UpdatedAt :               time . Now ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Shortcode :               shortcode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Domain :                  "" ,  // assume our own domain unless told otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageRemoteURL :          "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageStaticRemoteURL :    "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageURL :                "" ,                                                                                                     // we don't know yet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageStaticURL :          uris . GenerateURIForAttachment ( instanceAccount . ID ,  string ( TypeEmoji ) ,  string ( SizeStatic ) ,  id ,  mimePng ) ,  // all static emojis are encoded as png 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImagePath :               "" ,                                                                                                     // we don't know yet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageStaticPath :         fmt . Sprintf ( "%s/%s/%s/%s.%s" ,  instanceAccount . ID ,  TypeEmoji ,  SizeStatic ,  id ,  mimePng ) ,                  // all static emojis are encoded as png 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageContentType :        "" ,                                                                                                     // we don't know yet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageStaticContentType :  mimeImagePng ,                                                                                           // all static emojis are encoded as png 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageFileSize :           0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageStaticFileSize :     0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ImageUpdatedAt :          time . Now ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Disabled :                false , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										URI :                     uri , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										VisibleInPicker :         true , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CategoryID :              "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check if we have additional info to add to the emoji, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// and overwrite some of the emoji fields if so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ai  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ai . CreatedAt  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											emoji . CreatedAt  =  * ai . CreatedAt 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ai . Domain  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emoji . Domain  =  * ai . Domain 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ai . ImageRemoteURL  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emoji . ImageRemoteURL  =  * ai . ImageRemoteURL 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ai . ImageStaticRemoteURL  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emoji . ImageStaticRemoteURL  =  * ai . ImageStaticRemoteURL 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ai . Disabled  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emoji . Disabled  =  * ai . Disabled 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ai . VisibleInPicker  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emoji . VisibleInPicker  =  * ai . VisibleInPicker 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-15 14:33:58 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ai . CategoryID  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emoji . CategoryID  =  * ai . CategoryID 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									processingEmoji  :=  & ProcessingEmoji { 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:51:45 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										instanceAccountID :  instanceAccount . ID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										emoji :              emoji , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data :               data , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										staticState :        received , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fullSizeState :      received , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										database :           m . db , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										storage :            m . storage , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 17:49:14 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  processingEmoji ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}