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-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  visibility  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-24 13:54:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"codeberg.org/gruf/go-kv" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-24 13:54:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/id" 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/log" 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( f  * filter )  StatusHometimelineable ( ctx  context . Context ,  targetStatus  * gtsmodel . Status ,  timelineOwnerAccount  * gtsmodel . Account )  ( bool ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-02-17 12:02:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									l  :=  log . WithContext ( ctx ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										WithFields ( kv . Fields { { "statusID" ,  targetStatus . ID } } ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-24 13:54:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// don't timeline statuses more than 5 min in the future 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									maxID ,  err  :=  id . NewULIDFromTime ( time . Now ( ) . Add ( 5  *  time . Minute ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  targetStatus . ID  >  maxID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										l . Debug ( "status not hometimelineable because it's from more than 5 minutes in the future" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// status owner should always be able to see their own status in their timeline so we can return early if this is the case 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  targetStatus . AccountID  ==  timelineOwnerAccount . ID  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									v ,  err  :=  f . StatusVisible ( ctx ,  targetStatus ,  timelineOwnerAccount ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  fmt . Errorf ( "StatusHometimelineable: error checking visibility of status with id %s: %s" ,  targetStatus . ID ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! v  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										l . Debug ( "status is not hometimelineable because it's not visible to the requester" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  m  :=  range  targetStatus . Mentions  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  m . TargetAccountID  ==  timelineOwnerAccount . ID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// if we're mentioned we should be able to see the post 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// check we follow the originator of the status 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  targetStatus . Account  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tsa ,  err  :=  f . db . GetAccountByID ( ctx ,  targetStatus . AccountID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false ,  fmt . Errorf ( "StatusHometimelineable: error getting status author account with id %s: %s" ,  targetStatus . AccountID ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										targetStatus . Account  =  tsa 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									following ,  err  :=  f . db . IsFollowing ( ctx ,  timelineOwnerAccount ,  targetStatus . Account ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  fmt . Errorf ( "StatusHometimelineable: error checking if %s follows %s: %s" ,  timelineOwnerAccount . ID ,  targetStatus . AccountID ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! following  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Don't timeline a status whose parent hasn't been dereferenced yet or can't be dereferenced. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If we have the reply to URI but don't have an ID for the replied-to account or the replied-to status in our database, we haven't dereferenced it yet. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  targetStatus . InReplyToURI  !=  ""  &&  ( targetStatus . InReplyToID  ==  ""  ||  targetStatus . InReplyToAccountID  ==  "" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// if a status replies to an ID we know in the database, we need to check that parent status too 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  targetStatus . InReplyToID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// pin the reply to status on to this status if it hasn't been done already 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  targetStatus . InReplyTo  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											rs ,  err  :=  f . db . GetStatusByID ( ctx ,  targetStatus . InReplyToID ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												return  false ,  fmt . Errorf ( "StatusHometimelineable: error getting replied to status with id %s: %s" ,  targetStatus . InReplyToID ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											targetStatus . InReplyTo  =  rs 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// pin the reply to account on to this status if it hasn't been done already 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  targetStatus . InReplyToAccount  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ra ,  err  :=  f . db . GetAccountByID ( ctx ,  targetStatus . InReplyToAccountID ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												return  false ,  fmt . Errorf ( "StatusHometimelineable: error getting replied to account with id %s: %s" ,  targetStatus . InReplyToAccountID ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											targetStatus . InReplyToAccount  =  ra 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// if it's a reply to the timelineOwnerAccount, we don't need to check if the timelineOwnerAccount follows itself, just return true, they can see it 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  targetStatus . InReplyToAccountID  ==  timelineOwnerAccount . ID  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// make sure the parent status is also home timelineable, otherwise we shouldn't timeline this one either 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										parentStatusTimelineable ,  err  :=  f . StatusHometimelineable ( ctx ,  targetStatus . InReplyTo ,  timelineOwnerAccount ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  false ,  fmt . Errorf ( "StatusHometimelineable: error checking timelineability of parent status %s of status %s: %s" ,  targetStatus . InReplyToID ,  targetStatus . ID ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-18 23:23:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! parentStatusTimelineable  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-17 18:02:33 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  true ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}