mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 03:32:25 -05:00 
			
		
		
		
	
		
			
	
	
		
			120 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			120 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | // 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/>. | ||
|  | 
 | ||
|  | package processing | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"context" | ||
|  | 	"fmt" | ||
|  | 
 | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/federation" | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtscontext" | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/state" | ||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||
|  | ) | ||
|  | 
 | ||
|  | // GetParseMentionFunc returns a new ParseMentionFunc using the provided state and federator. | ||
|  | // State is used for doing local database lookups; federator is used for remote account lookups (if necessary). | ||
|  | func GetParseMentionFunc(state *state.State, federator *federation.Federator) gtsmodel.ParseMentionFunc { | ||
|  | 	return func(ctx context.Context, namestring string, originAccountID string, statusID string) (*gtsmodel.Mention, error) { | ||
|  | 		// Get the origin account first since | ||
|  | 		// we'll need it to create the mention. | ||
|  | 		originAcct, err := state.DB.GetAccountByID(ctx, originAccountID) | ||
|  | 		if err != nil { | ||
|  | 			return nil, fmt.Errorf( | ||
|  | 				"db error getting mention origin account %s: %w", | ||
|  | 				originAccountID, err, | ||
|  | 			) | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Parse target components from the | ||
|  | 		// "@someone@example.org" namestring. | ||
|  | 		targetUsername, targetHost, err := util.ExtractNamestringParts(namestring) | ||
|  | 		if err != nil { | ||
|  | 			return nil, fmt.Errorf( | ||
|  | 				"error extracting mention target: %w", | ||
|  | 				err, | ||
|  | 			) | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// It's a "local" mention if namestring | ||
|  | 		// looks like one of the following: | ||
|  | 		// | ||
|  | 		//   - "@someone" with no host component. | ||
|  | 		//   - "@someone@gts.example.org" and we're host "gts.example.org". | ||
|  | 		//   - "@someone@example.org" and we're account-domain "example.org". | ||
|  | 		local := targetHost == "" || | ||
|  | 			targetHost == config.GetHost() || | ||
|  | 			targetHost == config.GetAccountDomain() | ||
|  | 
 | ||
|  | 		// Either a local or remote | ||
|  | 		// target for the mention. | ||
|  | 		var targetAcct *gtsmodel.Account | ||
|  | 		if local { | ||
|  | 			// Lookup local target accounts in the db only. | ||
|  | 			targetAcct, err = state.DB.GetAccountByUsernameDomain(ctx, targetUsername, "") | ||
|  | 			if err != nil { | ||
|  | 				return nil, fmt.Errorf( | ||
|  | 					"db error getting mention local target account %s: %w", | ||
|  | 					targetUsername, err, | ||
|  | 				) | ||
|  | 			} | ||
|  | 		} else { | ||
|  | 			// If origin account is local, use | ||
|  | 			// it to do potential dereference. | ||
|  | 			// Else fallback to empty string, | ||
|  | 			// which uses instance account. | ||
|  | 			var requestUser string | ||
|  | 			if originAcct.IsLocal() { | ||
|  | 				requestUser = originAcct.Username | ||
|  | 			} | ||
|  | 
 | ||
|  | 			targetAcct, _, err = federator.GetAccountByUsernameDomain( | ||
|  | 				gtscontext.SetFastFail(ctx), | ||
|  | 				requestUser, | ||
|  | 				targetUsername, | ||
|  | 				targetHost, | ||
|  | 			) | ||
|  | 			if err != nil { | ||
|  | 				return nil, fmt.Errorf( | ||
|  | 					"error fetching mention remote target account: %w", | ||
|  | 					err, | ||
|  | 				) | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Return mention with useful populated fields, | ||
|  | 		// but *don't* store it in the database; that's | ||
|  | 		// up to the calling function to do, if they want. | ||
|  | 		return >smodel.Mention{ | ||
|  | 			ID:               id.NewULID(), | ||
|  | 			StatusID:         statusID, | ||
|  | 			OriginAccountID:  originAcct.ID, | ||
|  | 			OriginAccountURI: originAcct.URI, | ||
|  | 			OriginAccount:    originAcct, | ||
|  | 			TargetAccountID:  targetAcct.ID, | ||
|  | 			TargetAccountURI: targetAcct.URI, | ||
|  | 			TargetAccountURL: targetAcct.URL, | ||
|  | 			TargetAccount:    targetAcct, | ||
|  | 			NameString:       namestring, | ||
|  | 		}, nil | ||
|  | 	} | ||
|  | } |