2023-03-12 16:00:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GoToSocial  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Copyright (C) GoToSocial Authors admin@gotosocial.org  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SPDX-License-Identifier: AGPL-3.0-or-later  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// 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/>.  
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  dereferencing  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"slices" 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-26 15:34:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/ap" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/config" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/db" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/gtscontext" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/gtserror" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/gtsmodel" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/id" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/log" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/media" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/util" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"code.superseriousbusiness.org/gotosocial/internal/util/xslices" 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// statusFresh returns true if the given status is still  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// considered "fresh" according to the desired freshness  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// window (falls back to default status freshness if nil).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Local statuses will always be considered fresh,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// because there's no remote state that may have changed.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Return value of false indicates that the status  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is not fresh and should be refreshed from remote.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  statusFresh (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									window  * FreshnessWindow , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Take default if no 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// freshness window preferred. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  window  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										window  =  DefaultStatusFreshness 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-15 14:24:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  status . IsLocal ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Can't refresh 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// local statuses. 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  true 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-15 18:45:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Moment when the status is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// considered stale according to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// desired freshness window. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									staleAt  :=  status . FetchedAt . Add ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										time . Duration ( * window ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// It's still fresh if the time now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// is not past the point of staleness. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ! time . Now ( ) . After ( staleAt ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GetStatusByURI will attempt to fetch a status by its URI, first checking the database. In the case of a newly-met remote model, or a remote model whose 'last_fetched' date  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is beyond a certain interval, the status will be dereferenced. In the case of dereferencing, some low-priority status information may be enqueued for asynchronous fetching,  
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// e.g. dereferencing the status thread. An ActivityPub object indicates the status was dereferenced.  
						 
					
						
							
								
									
										
										
										
											2023-10-23 10:58:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  GetStatusByURI ( ctx  context . Context ,  requestUser  string ,  uri  * url . URL )  ( * gtsmodel . Status ,  ap . Statusable ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Fetch and dereference / update status if necessary. 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									status ,  statusable ,  isNew ,  err  :=  d . getStatusByURI ( ctx , 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uri , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  status  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// err with no existing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// status for fallback. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										log . Errorf ( ctx ,  "error updating status %s: %v" ,  uri ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  statusable  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Deref parents + children. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										d . dereferenceThread ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uri , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											statusable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											isNew , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  status ,  statusable ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// getStatusByURI is a package internal form of .GetStatusByURI() that doesn't dereference thread on update, and may return an existing status with error on failed re-fetch.  
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  getStatusByURI ( ctx  context . Context ,  requestUser  string ,  uri  * url . URL )  ( * gtsmodel . Status ,  ap . Statusable ,  bool ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status  * gtsmodel . Status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uriStr  =  uri . String ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err     error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Search the database for existing by URI. 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-31 09:39:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									status ,  err  =  d . state . DB . GetStatusByURI ( 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-31 09:39:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// request a barebones object, it may be in the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// db but with related models not yet dereferenced. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										gtscontext . SetBarebones ( ctx ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uriStr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  &&  ! errors . Is ( err ,  db . ErrNoEntries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  false ,  gtserror . Newf ( "error checking database for status %s by uri: %w" ,  uriStr ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-29 10:24:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  status  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Else, search database for existing by URL. 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-31 09:39:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										status ,  err  =  d . state . DB . GetStatusByURL ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											gtscontext . SetBarebones ( ctx ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uriStr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  &&  ! errors . Is ( err ,  db . ErrNoEntries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  nil ,  false ,  gtserror . Newf ( "error checking database for status %s by url: %w" ,  uriStr ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-29 10:24:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-23 17:40:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  status  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Ensure not a failed search for a local 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// status, if so we know it doesn't exist. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  uri . Host  ==  config . GetHost ( )  || 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uri . Host  ==  config . GetAccountDomain ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  nil ,  false ,  gtserror . SetUnretrievable ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-29 10:24:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Create and pass-through a new bare-bones model for deref. 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  d . enrichStatusSafely ( ctx ,  requestUser ,  uri ,  & gtsmodel . Status { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											Local :  util . Ptr ( false ) , 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											URI :    uriStr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ,  nil ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-29 10:24:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  statusFresh ( status ,  DefaultStatusFreshness )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-09 09:42:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// This is an existing status that is up-to-date, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// before returning ensure it is fully populated. 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-31 09:39:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . PopulateStatus ( ctx ,  status ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											log . Errorf ( ctx ,  "error populating existing status: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-09 09:42:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  status ,  nil ,  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-31 09:39:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Try to deref and update existing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  d . enrichStatusSafely ( ctx , 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uri , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nil , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// RefreshStatus is functionally equivalent to GetStatusByURI(), except that it requires a pre  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// populated status model (with AT LEAST uri set), and ALL thread dereferencing is asynchronous.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  RefreshStatus (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									statusable  ap . Statusable , 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									window  * FreshnessWindow , 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  ( * gtsmodel . Status ,  ap . Statusable ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-01-09 09:42:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If no incoming data is provided, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check whether status needs update. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  statusable  ==  nil  && 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										statusFresh ( status ,  window )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  status ,  nil ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Parse the URI from status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uri ,  err  :=  url . Parse ( status . URI ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "invalid status uri %q: %w" ,  status . URI ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Try to update + dereference the passed status model. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									latest ,  statusable ,  isNew ,  err  :=  d . enrichStatusSafely ( ctx , 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uri , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										statusable , 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  statusable  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Deref parents + children. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										d . dereferenceThread ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uri , 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-18 10:49:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											latest , 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											statusable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											isNew , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  latest ,  statusable ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// RefreshStatusAsync is functionally equivalent to RefreshStatus(), except that ALL  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// dereferencing is queued for asynchronous processing, (both thread AND status).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  RefreshStatusAsync (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									statusable  ap . Statusable , 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									window  * FreshnessWindow , 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
									
										
										
										
											2024-01-09 09:42:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If no incoming data is provided, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check whether status needs update. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  statusable  ==  nil  && 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 15:24:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										statusFresh ( status ,  window )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Parse the URI from status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uri ,  err  :=  url . Parse ( status . URI ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										log . Errorf ( ctx ,  "invalid status uri %q: %v" ,  status . URI ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Enqueue a worker function to re-fetch this status entirely async. 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 13:50:46 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									d . state . Workers . Dereference . Queue . Push ( func ( ctx  context . Context )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										latest ,  statusable ,  _ ,  err  :=  d . enrichStatusSafely ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uri , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											statusable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											log . Errorf ( ctx ,  "error enriching remote status: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  statusable  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  :=  d . DereferenceStatusAncestors ( ctx ,  requestUser ,  latest ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												log . Error ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  :=  d . DereferenceStatusDescendants ( ctx ,  requestUser ,  uri ,  statusable ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												log . Error ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// enrichStatusSafely wraps enrichStatus() to perform it within  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// a State{}.FedLocks mutexmap, which protects it within per-URI  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// mutex locks. This also handles necessary delete of now-deleted  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// statuses, and updating fetched_at on returned HTTP errors.  
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  enrichStatusSafely (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uri  * url . URL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 08:50:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									statusable  ap . Statusable , 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-04 20:21:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  ( * gtsmodel . Status ,  ap . Statusable ,  bool ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uriStr  :=  status . URI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-30 11:32:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  isNew  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check if this is a new status (to us). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  isNew  =  ( status . ID  ==  "" ) ;  ! isNew  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// This is an existing status, first try to populate it. This 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// is required by the checks below for existing tags, media etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . PopulateStatus ( ctx ,  status ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											log . Errorf ( ctx ,  "error populating existing status %s: %v" ,  uriStr ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Acquire per-URI deref lock, wraping unlock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// to safely defer in case of panic, while still 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// performing more granular unlocks when needed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unlock  :=  d . state . FedLocks . Lock ( uriStr ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-09 12:38:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unlock  =  util . DoOnce ( unlock ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Perform status enrichment with passed vars. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									latest ,  statusable ,  err  :=  d . enrichStatus ( ctx , 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uri , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 08:50:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										statusable , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										isNew , 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check for a returned HTTP code via error. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  code  :=  gtserror . StatusCode ( err ) ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Gone (410) definitely indicates deletion. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Remove status if it was an existing one. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  code  ==  http . StatusGone  &&  ! isNew : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . DeleteStatusByID ( ctx ,  status . ID ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											log . Error ( ctx ,  "error deleting gone status %s: %v" ,  uriStr ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Don't return any status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Any other HTTP error mesg 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// code, with existing status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  code  >=  400  &&  ! isNew : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Update fetched_at to slow re-attempts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// but don't return early. We can still 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// return the model we had stored already. 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										status . FetchedAt  =  time . Now ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . UpdateStatus ( ctx ,  status ,  "fetched_at" ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Error ( ctx ,  "error updating %s fetched_at: %v" ,  uriStr ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// See below. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fallthrough 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// In case of error with an existing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// status in the database, return error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// but still return existing status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  err  !=  nil  &&  ! isNew : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest  =  status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										statusable  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Unlock now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we're done. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errors . Is ( err ,  db . ErrAlreadyExists )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-30 11:32:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// We leave 'isNew' set so that caller 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// still dereferences parents, otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the version we pass back may not have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// these attached as inReplyTos yet (since 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// those happen OUTSIDE federator lock). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// TODO: performance-wise, this won't be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// great. should improve this if we can! 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// DATA RACE! We likely lost out to another goroutine 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// in a call to db.Put(Status). Look again in DB by URI. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest ,  err  =  d . state . DB . GetStatusByURI ( ctx ,  status . URI ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  =  gtserror . Newf ( "error getting status %s from database after race: %w" ,  uriStr ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  latest ,  statusable ,  isNew ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-24 09:32:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// enrichStatus will enrich the given status, whether a new  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// barebones model, or existing model from the database.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// It handles necessary dereferencing, database updates, etc.  
						 
					
						
							
								
									
										
										
										
											2023-10-23 10:58:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  enrichStatus (  
						 
					
						
							
								
									
										
										
										
											2023-06-24 09:32:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uri  * url . URL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									statusable  ap . Statusable , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									isNew  bool , 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ap . Statusable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Pre-fetch a transport for requesting username, used by later dereferencing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tsport ,  err  :=  d . transportController . NewTransportForUsername ( ctx ,  requestUser ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "couldn't create transport: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check whether this account URI is a blocked domain / subdomain. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  blocked ,  err  :=  d . state . DB . IsDomainBlocked ( ctx ,  uri . Host ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error checking blocked domain: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  blocked  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  gtserror . Newf ( "%s is blocked" ,  uri . Host ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-24 09:32:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . SetUnretrievable ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  statusable  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Dereference latest version of the status. 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-23 15:24:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										rsp ,  err  :=  tsport . Dereference ( ctx ,  uri ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "error dereferencing %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  nil ,  gtserror . SetUnretrievable ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-23 15:24:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Attempt to resolve ActivityPub status from response. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										statusable ,  err  =  ap . ResolveStatusable ( ctx ,  rsp . Body ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-23 15:24:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Tidy up now done. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_  =  rsp . Body . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-23 15:24:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// ResolveStatusable will set gtserror.WrongType 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// on the returned error, so we don't need to do it here. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "error resolving statusable %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-23 15:24:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Check whether input URI and final returned URI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// have changed (i.e. we followed some redirects). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  finalURIStr  :=  rsp . Request . URL . String ( ) ;  // 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										finalURIStr  !=  uri . String ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// NOTE: this URI check + database call is performed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// AFTER reading and closing response body, for performance. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Check whether we have this status stored under *final* URI. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											alreadyStatus ,  err  :=  d . state . DB . GetStatusByURI ( ctx ,  finalURIStr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  &&  ! errors . Is ( err ,  db . ErrNoEntries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  nil ,  gtserror . Newf ( "db error getting status after redirects: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  alreadyStatus  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// We had this status stored 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// under discovered final URI. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// Proceed with this status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												status  =  alreadyStatus 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Update the input URI to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// the final determined URI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// for later URI checks. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											uri  =  rsp . Request . URL 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 17:49:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Get the attributed-to account in order to fetch profile. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									attributedTo ,  err  :=  ap . ExtractAttributedToURI ( statusable ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . New ( "attributedTo was empty" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-12 13:03:23 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Ensure we have the author account of the status dereferenced (+ up-to-date). If this is a new status 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 11:13:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// (i.e. status.AccountID == "") then any error here is irrecoverable. status.AccountID must ALWAYS be set. 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// We want the exact URI match here as well, not the imprecise URL match. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  _ ,  err  :=  d . getAccountByURI ( ctx ,  requestUser ,  attributedTo ,  false ) ;  err  !=  nil  &&  status . AccountID  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Note that we specifically DO NOT wrap the error, instead collapsing it as string. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Errors fetching an account do not necessarily relate to dereferencing the status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "failed to dereference status author %s: %v" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// ActivityPub model was recently dereferenced, so assume passed status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// may contain out-of-date information. Convert AP model to our GTS model. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									latestStatus ,  err  :=  d . converter . ASStatusToStatus ( ctx ,  statusable ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error converting statusable to gts model for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 11:13:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Ensure final status isn't attempting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// to claim being authored by local user. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  latestStatus . Account . IsLocal ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"dereferenced status %s claiming to be local" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											latestStatus . URI , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-26 13:11:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Ensure the final parsed status URI or URL matches 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 11:13:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// the input URI we fetched (or received) it as. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									matches ,  err  :=  util . URIMatches ( uri , 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-26 13:11:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										append ( 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ap . GetURL ( statusable ) ,       // status URL(s) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ap . GetJSONLDId ( statusable ) ,  // status URI 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-26 13:11:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										) ... , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"error checking dereferenced status uri %s: %w" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											latestStatus . URI ,  err , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! matches  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 11:13:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"dereferenced status uri %s does not match %s" , 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-26 13:11:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											latestStatus . URI ,  uri . String ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 11:13:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isNew  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Generate new status ID from the provided creation date. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										latestStatus . ID  =  id . NewULIDFromTime ( latestStatus . CreatedAt ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 13:29:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-24 21:16:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Ensure that status isn't trying to re-date itself. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! latestStatus . CreatedAt . Equal ( status . CreatedAt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "status %s 'published' changed" ,  uri ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  nil ,  gtserror . SetMalformed ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Reuse existing status ID. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus . ID  =  status . ID 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 14:46:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Set latest fetch time and carry- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// over some values from "old" status. 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									latestStatus . FetchedAt  =  time . Now ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									latestStatus . Local  =  status . Local 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 14:46:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									latestStatus . PinnedAt  =  status . PinnedAt 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-25 12:18:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Carry-over approvals. Remote instances might not yet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// serve statuses with the `approved_by` field, but we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// might have marked a status as pre-approved on our side 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// based on the author's inclusion in a followers/following 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-08 10:51:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// collection, or by providing pre-approval URI on the bare 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// status passed to RefreshStatus. By carrying over previously 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// set values we can avoid marking such statuses as "pending". 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-25 12:18:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If a remote has in the meantime retracted its approval, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// the next call to 'isPermittedStatus' will catch that. 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-25 15:44:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  latestStatus . ApprovedByURI  ==  ""  &&  status . ApprovedByURI  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus . ApprovedByURI  =  status . ApprovedByURI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-25 12:18:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 12:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check if this is a permitted status we should accept. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Function also sets "PendingApproval" bool as necessary, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// and handles removal of existing statuses no longer permitted. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									permit ,  err  :=  d . isPermittedStatus ( ctx ,  requestUser ,  status ,  latestStatus ,  isNew ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 12:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error checking permissibility for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! permit  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Return a checkable error type that can be ignored. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  gtserror . Newf ( "dropping unpermitted status: %s" ,  uri ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . SetNotPermitted ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 14:32:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Insert / update any attached status poll. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pollChanged ,  err  :=  d . handleStatusPoll ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error handling poll for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Populate mentions associated with status, passing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// in existing status to reuse old where possible. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// (especially important here to reduce need to dereference). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mentionsChanged ,  err  :=  d . fetchStatusMentions ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error populating mentions for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-04 12:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Ensure status in a thread is connected. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									threadChanged ,  err  :=  d . threadStatus ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error handling threading for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Populate tags associated with status, passing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// in existing status to reuse old where possible. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tagsChanged ,  err  :=  d . fetchStatusTags ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error populating tags for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Populate media attachments associated with status, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// passing in existing status to reuse old where possible 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// (especially important here to reduce need to dereference). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mediaChanged ,  err  :=  d . fetchStatusAttachments ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error populating attachments for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Populate emoji associated with status, passing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// in existing status to reuse old where possible 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// (especially important here to reduce need to dereference). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									emojiChanged ,  err  :=  d . fetchStatusEmojis ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-28 13:08:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  nil ,  gtserror . Newf ( "error populating emojis for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 14:17:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  isNew  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Simplest case, insert this new status into the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . PutStatus ( ctx ,  latestStatus ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  nil ,  gtserror . Newf ( "error inserting new status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Check for and handle any edits to status, inserting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// historical edit if necessary. Also determines status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// columns that need updating in below query. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols ,  err  :=  d . handleStatusEdit ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											latestStatus , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pollChanged , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mentionsChanged , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											threadChanged , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tagsChanged , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mediaChanged , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emojiChanged , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  nil ,  gtserror . Newf ( "error handling edit for status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// With returned changed columns, now update the existing status entry. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . UpdateStatus ( ctx ,  latestStatus ,  cols ... ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  nil ,  gtserror . Newf ( "error updating existing status %s: %w" ,  uri ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 14:08:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  latestStatus ,  statusable ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// fetchStatusMentions populates the mentions on 'status', creating  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// new where needed, or using unchanged mentions from 'existing' status.  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  fetchStatusMentions (  
						 
					
						
							
								
									
										
										
										
											2023-10-31 12:05:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									changed  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Get most-recent modified time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// for use in new mention ULIDs. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									updatedAt  :=  status . UpdatedAt ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 12:05:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Allocate new slice to take the yet-to-be created mention IDs. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . MentionIDs  =  make ( [ ] string ,  len ( status . Mentions ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  status . Mentions  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mention        =  status . Mentions [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											alreadyExists  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Search existing status for a mention already stored, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// else ensure new mention's target account is populated. 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mention ,  alreadyExists ,  err  =  d . populateMentionTarget ( ctx , 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 12:05:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											existing , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											mention , 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 12:05:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											log . Errorf ( ctx ,  "failed to derive mention: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  alreadyExists  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// This mention was already attached 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// to the status, use it and continue. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . Mentions [ i ]  =  mention 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . MentionIDs [ i ]  =  mention . ID 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Mark status as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// having changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										changed  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 12:05:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// This mention didn't exist yet. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Generate new ID according to latest update. 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mention . ID  =  id . NewULIDFromTime ( updatedAt ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Set further mention details. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . CreatedAt  =  updatedAt 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mention . OriginAccount  =  status . Account 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . OriginAccountID  =  status . AccountID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . OriginAccountURI  =  status . AccountURI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . TargetAccountID  =  mention . TargetAccount . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . TargetAccountURI  =  mention . TargetAccount . URI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . TargetAccountURL  =  mention . TargetAccount . URL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . StatusID  =  status . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mention . Status  =  status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Place the new mention into the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . PutMention ( ctx ,  mention ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  changed ,  gtserror . Newf ( "error putting mention in database: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Set the *new* mention and ID. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Mentions [ i ]  =  mention 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . MentionIDs [ i ]  =  mention . ID 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  len ( status . MentionIDs ) ;  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  status . MentionIDs [ i ]  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// This is a failed mention population, likely due 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// to invalid incoming data / now-deleted accounts. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											copy ( status . Mentions [ i : ] ,  status . Mentions [ i + 1 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											copy ( status . MentionIDs [ i : ] ,  status . MentionIDs [ i + 1 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . Mentions  =  status . Mentions [ : len ( status . Mentions ) - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . MentionIDs  =  status . MentionIDs [ : len ( status . MentionIDs ) - 1 ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										i ++ 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  changed ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// threadStatus ensures that given status is threaded correctly  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// where necessary. that is it will inherit a thread ID from the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// existing copy if it is threaded correctly, else it will inherit  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// a thread ID from a parent with existing thread, else it will  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// generate a new thread ID if status mentions a local account.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  threadStatus (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									changed  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check for existing status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// that is already threaded. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  existing . ThreadID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Existing is threaded correctly. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  existing . InReplyTo  ==  nil  || 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											existing . InReplyTo . ThreadID  ==  existing . ThreadID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . ThreadID  =  existing . ThreadID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// TODO: delete incorrect thread 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check for existing parent to inherit threading from. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  inReplyTo  :=  status . InReplyTo ;  inReplyTo  !=  nil  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										inReplyTo . ThreadID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . ThreadID  =  inReplyTo . ThreadID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  true ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Parent wasn't threaded. If this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// status mentions a local account, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we should thread it so that local 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// account can mute it if they want. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mentionsLocal  :=  slices . ContainsFunc ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Mentions , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										func ( m  * gtsmodel . Mention )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// If TargetAccount couldn't 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// be deref'd, we know it's not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// a local account, so only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// check for non-nil accounts. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  m . TargetAccount  !=  nil  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												m . TargetAccount . IsLocal ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! mentionsLocal  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Status doesn't mention a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// local account, so we don't 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// need to thread it. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Status mentions a local account. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Create a new thread and assign 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// it to the status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									threadID  :=  id . NewULID ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Insert new thread model into db. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  d . state . DB . PutThread ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& gtsmodel . Thread { ID :  threadID } , 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  false ,  gtserror . Newf ( "error inserting new thread in db: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Set thread on latest status. 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									status . ThreadID  =  threadID 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  true ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 16:04:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// fetchStatusTags populates the tags on 'status', fetching existing  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// from the database and creating new where needed. 'existing' is used  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// to fetch tags that have not changed since previous stored status.  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  fetchStatusTags (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									changed  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Allocate new slice to take the yet-to-be determined tag IDs. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . TagIDs  =  make ( [ ] string ,  len ( status . Tags ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  status . Tags  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										tag  :=  status . Tags [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Look for tag in existing status with name. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										existing ,  ok  :=  existing . GetTagByName ( tag . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ok  &&  existing . ID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . Tags [ i ]  =  existing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . TagIDs [ i ]  =  existing . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Mark status as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// having changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										changed  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Look for existing tag with name in the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										existing ,  err  :=  d . state . DB . GetTagByName ( ctx ,  tag . Name ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  &&  ! errors . Is ( err ,  db . ErrNoEntries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  changed ,  gtserror . Newf ( "db error getting tag %s: %w" ,  tag . Name ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  existing  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . Tags [ i ]  =  existing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . TagIDs [ i ]  =  existing . ID 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Create new ID for tag. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tag . ID  =  id . NewULID ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Insert this tag with new name into the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . PutTag ( ctx ,  tag ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											log . Errorf ( ctx ,  "db error putting tag %s: %v" ,  tag . Name ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Set new tag ID in slice. 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-31 15:47:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										status . TagIDs [ i ]  =  tag . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Remove any tag we couldn't get or create. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  len ( status . TagIDs ) ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  status . TagIDs [ i ]  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// This is a failed tag population, likely due 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// to some database peculiarity / race condition. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											copy ( status . Tags [ i : ] ,  status . Tags [ i + 1 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											copy ( status . TagIDs [ i : ] ,  status . TagIDs [ i + 1 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . Tags  =  status . Tags [ : len ( status . Tags ) - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . TagIDs  =  status . TagIDs [ : len ( status . TagIDs ) - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  changed ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 14:32:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// fetchStatusAttachments populates the attachments on 'status', creating new database  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// entries where needed and dereferencing it, or using unchanged from 'existing' status.  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  fetchStatusAttachments (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									changed  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Allocate new slice to take the yet-to-be fetched attachment IDs. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . AttachmentIDs  =  make ( [ ] string ,  len ( status . Attachments ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  status . Attachments  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										placeholder  :=  status . Attachments [ i ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-10 19:29:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Look for existing media attachment with remote URL first. 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										existing ,  ok  :=  existing . GetAttachmentByRemoteURL ( placeholder . RemoteURL ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ok  &&  existing . ID  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											var  info  media . AdditionalMediaInfo 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// Look for any difference in stored media description. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											diff  :=  ( existing . Description  !=  placeholder . Description ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  diff  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												info . Description  =  & placeholder . Description 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// If description changed, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// we mark media as changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											changed  =  changed  ||  diff 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Store any attachment updates and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// ensure media is locally cached. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											existing ,  err  :=  d . RefreshMedia ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												existing , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												info , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												diff , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												log . Errorf ( ctx ,  "error updating existing attachment: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// specifically do NOT continue here, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// we already have a model, we don't 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// want to drop it from the status, just 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// log that an update for it failed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Set the existing attachment. 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											status . Attachments [ i ]  =  existing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . AttachmentIDs [ i ]  =  existing . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Mark status as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// having changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										changed  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Load this new media attachment. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										attachment ,  err  :=  d . GetMedia ( ctx , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											status . AccountID , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											placeholder . RemoteURL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											media . AdditionalMediaInfo { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												StatusID :     & status . ID , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												RemoteURL :    & placeholder . RemoteURL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Description :  & placeholder . Description , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Blurhash :     & placeholder . Blurhash , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-26 15:03:05 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												FocusX :       & placeholder . FileMeta . Focus . X , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												FocusY :       & placeholder . FileMeta . Focus . Y , 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-06 14:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-08 17:17:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  attachment  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												log . Errorf ( ctx ,  "error loading attachment %s: %v" ,  placeholder . RemoteURL ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// non-fatal error occurred during loading, still use it. 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-10 19:29:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											log . Warnf ( ctx ,  "partially loaded attachment: %v" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Set the *new* attachment and ID. 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-31 11:12:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										status . Attachments [ i ]  =  attachment 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . AttachmentIDs [ i ]  =  attachment . ID 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  len ( status . AttachmentIDs ) ;  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  status . AttachmentIDs [ i ]  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-10 19:29:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// Remove totally failed attachment populations 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											copy ( status . Attachments [ i : ] ,  status . Attachments [ i + 1 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											copy ( status . AttachmentIDs [ i : ] ,  status . AttachmentIDs [ i + 1 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . Attachments  =  status . Attachments [ : len ( status . Attachments ) - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											status . AttachmentIDs  =  status . AttachmentIDs [ : len ( status . AttachmentIDs ) - 1 ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 20:46:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										i ++ 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-12 10:15:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  changed ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// fetchStatusEmojis populates the emojis on 'status', creating new database entries  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// where needed and dereferencing it, or using unchanged from 'existing' status.  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  fetchStatusEmojis (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									changed  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Fetch the updated emojis for our status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									emojis ,  changed ,  err  :=  d . fetchEmojis ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										existing . Emojis , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Emojis , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 11:56:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  changed ,  gtserror . Newf ( "error fetching emojis: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 11:56:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-12 13:03:23 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! changed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Use existing status emoji objects. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . EmojiIDs  =  existing . EmojiIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Emojis  =  existing . Emojis 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-12 13:03:23 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Set latest emojis. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 11:56:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									status . Emojis  =  emojis 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-23 17:54:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Extract IDs from latest slice of emojis. 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									status . EmojiIDs  =  make ( [ ] string ,  len ( emojis ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  emoji  :=  range  emojis  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . EmojiIDs [ i ]  =  emoji . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-29 12:03:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-23 17:54:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Combine both old and new emojis, as statuses.emojis 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// keeps track of emojis for both old and current edits. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . EmojiIDs  =  append ( status . EmojiIDs ,  existing . EmojiIDs ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . Emojis  =  append ( status . Emojis ,  existing . Emojis ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . EmojiIDs  =  xslices . Deduplicate ( status . EmojiIDs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . Emojis  =  xslices . DeduplicateFunc ( status . Emojis , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										func ( e  * gtsmodel . Emoji )  string  {  return  e . ID  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// handleStatusPoll handles both inserting of new status poll or the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// update of an existing poll. this handles the case of simple vote  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// count updates (without being classified as a change of the poll  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// itself), as well as full poll changes that delete existing instance.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  handleStatusPoll (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									changed  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  existing . Poll  ==  nil  &&  status . Poll  ==  nil : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// no poll before or after, nothing to do. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  existing . Poll  ==  nil  &&  status . Poll  !=  nil : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// no previous poll, insert new status poll! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  true ,  d . insertStatusPoll ( ctx ,  status ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  status . Poll  ==  nil : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// existing status poll has been deleted, remove this from the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  =  d . state . DB . DeletePollByID ( ctx ,  existing . Poll . ID ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  =  gtserror . Newf ( "error deleting poll from database: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  true ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  pollChanged ( existing . Poll ,  status . Poll ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// existing status poll has been changed, remove this from the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  =  d . state . DB . DeletePollByID ( ctx ,  existing . Poll . ID ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true ,  gtserror . Newf ( "error deleting poll from database: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// insert latest poll version into database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  true ,  d . insertStatusPoll ( ctx ,  status ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  pollStateUpdated ( existing . Poll ,  status . Poll ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Since we last saw it, the poll has updated! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Whether that be stats, or close time. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poll  :=  existing . Poll 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poll . Closing  =  pollJustClosed ( existing . Poll ,  status . Poll ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poll . ClosedAt  =  status . Poll . ClosedAt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poll . Voters  =  status . Poll . Voters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poll . Votes  =  status . Poll . Votes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Update poll model in the database (specifically only the possible changed columns). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  =  d . state . DB . UpdatePoll ( ctx ,  poll ,  "closed_at" ,  "voters" ,  "votes" ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false ,  gtserror . Newf ( "error updating poll: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Update poll on status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . PollID  =  poll . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Poll  =  poll 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// latest and existing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// polls are up to date. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										poll  :=  existing . Poll 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . PollID  =  poll . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Poll  =  poll 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// insertStatusPoll inserts an assumed new poll attached to status into the database, this  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// also handles generating new ID for the poll and setting necessary fields on the status.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  insertStatusPoll ( ctx  context . Context ,  status  * gtsmodel . Status )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Get most-recent modified time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// which will be poll creation time. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									createdAt  :=  status . UpdatedAt ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Generate new ID for poll from createdAt. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . Poll . ID  =  id . NewULIDFromTime ( createdAt ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Update the status<->poll links. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . PollID  =  status . Poll . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . Poll . StatusID  =  status . ID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . Poll . Status  =  status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Insert this latest poll into the database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  =  d . state . DB . PutPoll ( ctx ,  status . Poll ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  gtserror . Newf ( "error putting poll in database: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 13:32:39 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// handleStatusEdit compiles a list of changed status table columns between  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// existing and latest status model, and where necessary inserts a historic  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// edit of the status into the database to store its previous state. the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// returned slice is a list of columns requiring updating in the database.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  handleStatusEdit (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pollChanged  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mentionsChanged  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									threadChanged  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tagsChanged  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mediaChanged  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									emojiChanged  bool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cols  [ ] string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  edited  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Copy previous status edit columns. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . EditIDs  =  existing . EditIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									status . Edits  =  existing . Edits 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Preallocate max slice length. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-23 17:54:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cols  =  make ( [ ] string ,  1 ,  13 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Always update `fetched_at`. 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-23 17:54:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cols [ 0 ]  =  "fetched_at" 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check for edited status content. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  existing . Content  !=  status . Content  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "content" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edited  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check for edited status content warning. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  existing . ContentWarning  !=  status . ContentWarning  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "content_warning" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edited  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check for edited status sensitive flag. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  * existing . Sensitive  !=  * status . Sensitive  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "sensitive" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edited  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check for edited status language tag. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  existing . Language  !=  status . Language  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "language" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edited  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  pollChanged  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Attached poll was changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "poll_id" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edited  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  mentionsChanged  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "mentions" )  // i.e. MentionIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Mentions changed doesn't necessarily 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// indicate an edit, it may just not have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// been previously populated properly. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  threadChanged  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "thread_id" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Thread changed doesn't necessarily 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// indicate an edit, it may just now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// actually be included in a thread. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  tagsChanged  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "tags" )  // i.e. TagIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Tags changed doesn't necessarily 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// indicate an edit, it may just not have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// been previously populated properly. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  mediaChanged  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Attached media was changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "attachments" )  // i.e. AttachmentIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edited  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  emojiChanged  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Attached emojis changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "emojis" )  // i.e. EmojiIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-23 17:54:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// We specifically store both *new* AND *old* edit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// revision emojis in the statuses.emojis column. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										emojiByID  :=  func ( e  * gtsmodel . Emoji )  string  {  return  e . ID  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Emojis  =  append ( status . Emojis ,  existing . Emojis ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Emojis  =  xslices . DeduplicateFunc ( status . Emojis ,  emojiByID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . EmojiIDs  =  xslices . Gather ( status . EmojiIDs [ : 0 ] ,  status . Emojis ,  emojiByID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Emojis changed doesn't necessarily 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// indicate an edit, it may just not have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// been previously populated properly. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  edited  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Get previous-most-recent modified time, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// which will be this edit's creation time. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										createdAt  :=  existing . UpdatedAt ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Status has been editted since last 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// we saw it, take snapshot of existing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  edit  gtsmodel . StatusEdit 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										edit . ID  =  id . NewULIDFromTime ( createdAt ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										edit . Content  =  existing . Content 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edit . ContentWarning  =  existing . ContentWarning 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edit . Text  =  existing . Text 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-06 11:31:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										edit . ContentType  =  existing . ContentType 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										edit . Language  =  existing . Language 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edit . Sensitive  =  existing . Sensitive 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edit . StatusID  =  status . ID 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										edit . CreatedAt  =  createdAt 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Copy existing attachments and descriptions. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edit . AttachmentIDs  =  existing . AttachmentIDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										edit . Attachments  =  existing . Attachments 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  l  :=  len ( existing . Attachments ) ;  l  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											edit . AttachmentDescriptions  =  make ( [ ] string ,  l ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  i ,  attach  :=  range  existing . Attachments  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												edit . AttachmentDescriptions [ i ]  =  attach . Description 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  existing . Poll  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Poll only set if existing contained them. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											edit . PollOptions  =  existing . Poll . Options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-23 17:54:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  pollChanged  ||  ! * existing . Poll . HideCounts  || 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												! existing . Poll . ClosedAt . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// If the counts are allowed to be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// shown, or poll has changed, then 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// include poll vote counts in edit. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												edit . PollVotes  =  existing . Poll . Votes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Insert this new edit of existing status into database. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  d . state . DB . PutStatusEdit ( ctx ,  & edit ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  gtserror . Newf ( "error putting edit in database: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Add edit to list of edits on the status. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . EditIDs  =  append ( status . EditIDs ,  edit . ID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										status . Edits  =  append ( status . Edits ,  & edit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-24 21:16:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Add edit to list of cols. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "edits" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! existing . EditedAt . Equal ( status . EditedAt )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-24 21:16:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Whether status edited or not, 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-08 10:29:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// edited_at column has changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cols  =  append ( cols ,  "edited_at" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-05 13:35:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cols ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// populateMentionTarget tries to populate the given  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// mention with the correct TargetAccount and (if not  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// yet set) TargetAccountURI, returning the populated  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// mention.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Will check on the existing status if the mention  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is already there and populated; if so, existing  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// mention will be returned along with `true`.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Otherwise, this function will try to parse first  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the Href of the mention, and then the namestring,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// to see who it targets, and go fetch that account.  
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note: Ordinarily it would make sense to try the  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// namestring first, as it definitely can't be a URL  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// rather than a URI, but because some remotes do  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// silly things like only provide `@username` instead  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// of `@username@domain`, we try by URI first.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( d  * Dereferencer )  populateMentionTarget (  
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									requestUser  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									existing  * gtsmodel . Status , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mention  * gtsmodel . Mention , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* gtsmodel . Mention , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool ,  // True if mention already exists in the DB. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  {  
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Mentions can be created using `name` or `href`. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Prefer `href` (TargetAccountURI), fall back to Name. 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  mention . TargetAccountURI  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Look for existing mention with target account's URI, if so use this. 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										existingMention ,  ok  :=  existing . GetMentionByTargetURI ( mention . TargetAccountURI ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ok  &&  existingMention . ID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  existingMention ,  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Ensure that mention account URI is parseable. 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										targetAccountURI ,  err  :=  url . Parse ( mention . TargetAccountURI ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "invalid account uri %q: %w" ,  mention . TargetAccountURI ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Ensure we have the account of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the mention target dereferenced. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Use exact URI match only, not URL, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// as we want to be precise here. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mention . TargetAccount ,  _ ,  err  =  d . getAccountByURI ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											targetAccountURI , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											false , 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "failed to dereference account %s: %w" ,  targetAccountURI ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Href wasn't set, extract the username and domain parts from namestring. 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										username ,  domain ,  err  :=  util . ExtractNamestringParts ( mention . NameString ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "failed to parse namestring %s: %w" ,  mention . NameString ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Look for existing mention with username domain target, if so use this. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										existingMention ,  ok  :=  existing . GetMentionByUsernameDomain ( username ,  domain ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ok  &&  existingMention . ID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  existingMention ,  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Ensure we have the account of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the mention target dereferenced. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This might fail if the remote does 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// something silly like only setting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// `@username` and not `@username@domain`. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mention . TargetAccount ,  _ ,  err  =  d . getAccountByUsernameDomain ( ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											requestUser , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											username , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											domain , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  &&  ! errors . Is ( err ,  db . ErrNoEntries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( "failed to dereference account %s: %w" ,  mention . NameString ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-06 14:39:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  mention . TargetAccount  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// Probably failed for abovementioned 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// silly reason. Nothing we can do about it. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  :=  gtserror . Newf ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												"failed to populate mention target account (badly formatted namestring?) %s: %w" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												mention . NameString ,  err , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 12:33:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Look for existing mention with target account's URI, if so use this. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										existingMention ,  ok  =  existing . GetMentionByTargetURI ( mention . TargetAccountURI ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-26 15:01:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ok  &&  existingMention . ID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  existingMention ,  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// At this point, mention.TargetAccountURI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// and mention.TargetAccount must be set. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  mention ,  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}