mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 23:02:25 -05:00 
			
		
		
		
	start working on parent/child statuses
This commit is contained in:
		
					parent
					
						
							
								a42e05eee0
							
						
					
				
			
			
				commit
				
					
						6a053ecfd8
					
				
			
		
					 5 changed files with 130 additions and 4 deletions
				
			
		|  | @ -217,6 +217,12 @@ type DB interface { | ||||||
| 	// GetFaveCountForStatus returns the amount of faves/likes recorded for a status, or an error if something goes wrong | 	// GetFaveCountForStatus returns the amount of faves/likes recorded for a status, or an error if something goes wrong | ||||||
| 	GetFaveCountForStatus(status *gtsmodel.Status) (int, error) | 	GetFaveCountForStatus(status *gtsmodel.Status) (int, error) | ||||||
| 
 | 
 | ||||||
|  | 	// StatusParents get the parent statuses of a given status. | ||||||
|  | 	StatusParents(status *gtsmodel.Status) ([]*gtsmodel.Status, error) | ||||||
|  | 
 | ||||||
|  | 	// StatusChildren gets the child statuses of a given status. | ||||||
|  | 	StatusChildren(status *gtsmodel.Status) ([]*gtsmodel.Status, error) | ||||||
|  | 
 | ||||||
| 	// StatusFavedBy checks if a given status has been faved by a given account ID | 	// StatusFavedBy checks if a given status has been faved by a given account ID | ||||||
| 	StatusFavedBy(status *gtsmodel.Status, accountID string) (bool, error) | 	StatusFavedBy(status *gtsmodel.Status, accountID string) (bool, error) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -807,14 +807,26 @@ func (ps *postgresService) GetRelationship(requestingAccount string, targetAccou | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ps *postgresService) Follows(sourceAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (bool, error) { | func (ps *postgresService) Follows(sourceAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (bool, error) { | ||||||
|  | 	if sourceAccount == nil || targetAccount == nil { | ||||||
|  | 		return false, nil | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	return ps.conn.Model(>smodel.Follow{}).Where("account_id = ?", sourceAccount.ID).Where("target_account_id = ?", targetAccount.ID).Exists() | 	return ps.conn.Model(>smodel.Follow{}).Where("account_id = ?", sourceAccount.ID).Where("target_account_id = ?", targetAccount.ID).Exists() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ps *postgresService) FollowRequested(sourceAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (bool, error) { | func (ps *postgresService) FollowRequested(sourceAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (bool, error) { | ||||||
|  | 	if sourceAccount == nil || targetAccount == nil { | ||||||
|  | 		return false, nil | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	return ps.conn.Model(>smodel.FollowRequest{}).Where("account_id = ?", sourceAccount.ID).Where("target_account_id = ?", targetAccount.ID).Exists() | 	return ps.conn.Model(>smodel.FollowRequest{}).Where("account_id = ?", sourceAccount.ID).Where("target_account_id = ?", targetAccount.ID).Exists() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ps *postgresService) Mutuals(account1 *gtsmodel.Account, account2 *gtsmodel.Account) (bool, error) { | func (ps *postgresService) Mutuals(account1 *gtsmodel.Account, account2 *gtsmodel.Account) (bool, error) { | ||||||
|  | 	if account1 == nil || account2 == nil { | ||||||
|  | 		return false, nil | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	// make sure account 1 follows account 2 | 	// make sure account 1 follows account 2 | ||||||
| 	f1, err := ps.conn.Model(>smodel.Follow{}).Where("account_id = ?", account1.ID).Where("target_account_id = ?", account2.ID).Exists() | 	f1, err := ps.conn.Model(>smodel.Follow{}).Where("account_id = ?", account1.ID).Where("target_account_id = ?", account2.ID).Exists() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								internal/db/pg/statuscontext.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								internal/db/pg/statuscontext.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | package pg | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"sync" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func (ps *postgresService) StatusParents(status *gtsmodel.Status) ([]*gtsmodel.Status, error) { | ||||||
|  | 	parents := []*gtsmodel.Status{} | ||||||
|  | 	ps.statusParent(status, &parents) | ||||||
|  | 
 | ||||||
|  | 	return parents, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ps *postgresService) statusParent(status *gtsmodel.Status, foundStatuses *[]*gtsmodel.Status) { | ||||||
|  | 	if status.InReplyToID == "" { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	parentStatus := >smodel.Status{} | ||||||
|  | 	if err := ps.conn.Model(parentStatus).Where("id = ?", status.InReplyToID).Select(); err == nil { | ||||||
|  | 		*foundStatuses = append(*foundStatuses, parentStatus) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ps.statusParent(parentStatus, foundStatuses) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ps *postgresService) StatusChildren(status *gtsmodel.Status) ([]*gtsmodel.Status, error) { | ||||||
|  | 	children := []*gtsmodel.Status{} | ||||||
|  | 	// ps.statusChildren(status, &children) | ||||||
|  | 	 | ||||||
|  | 	return children, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ps *postgresService) statusChildren(status *gtsmodel.Status, foundStatuses *sync.Map) { | ||||||
|  | 	// immediateChildren := []*gtsmodel.Status{} | ||||||
|  | 	 | ||||||
|  | 	// foundStatuses.Store() | ||||||
|  | 
 | ||||||
|  | 	// err := ps.conn.Model(&immediateChildren).Where("in_reply_to_id = ?", status.ID).Select() | ||||||
|  | 	// if err != nil { | ||||||
|  | 	// 	return | ||||||
|  | 	// } | ||||||
|  | 
 | ||||||
|  | 	// for _, child := range immediateChildren { | ||||||
|  | 	// 	f[""][0] = child | ||||||
|  | 	// } | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | @ -1,14 +1,73 @@ | ||||||
| package status | package status | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"sort" | ||||||
|  | 
 | ||||||
| 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) Context(account *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode) { | func (p *processor) Context(account *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode) { | ||||||
| 	return &apimodel.Context{ | 
 | ||||||
|  | 	context := &apimodel.Context{ | ||||||
| 		Ancestors:   []apimodel.Status{}, | 		Ancestors:   []apimodel.Status{}, | ||||||
| 		Descendants: []apimodel.Status{}, | 		Descendants: []apimodel.Status{}, | ||||||
| 	}, nil | 	} | ||||||
|  | 
 | ||||||
|  | 	targetStatus := >smodel.Status{} | ||||||
|  | 	if err := p.db.GetByID(targetStatusID, targetStatus); err != nil { | ||||||
|  | 		if _, ok := err.(db.ErrNoEntries); ok { | ||||||
|  | 			return nil, gtserror.NewErrorNotFound(err) | ||||||
|  | 		} | ||||||
|  | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	visible, err := p.filter.StatusVisible(targetStatus, account) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, gtserror.NewErrorNotFound(err) | ||||||
|  | 	} | ||||||
|  | 	if !visible { | ||||||
|  | 		return nil, gtserror.NewErrorForbidden(fmt.Errorf("account with id %s does not have permission to view status %s", account.ID, targetStatusID)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	parents, err := p.db.StatusParents(targetStatus) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, status := range parents { | ||||||
|  | 		if v, err := p.filter.StatusVisible(status, account); err == nil && v { | ||||||
|  | 			mastoStatus, err := p.tc.StatusToMasto(status, account) | ||||||
|  | 			if err == nil { | ||||||
|  | 				context.Ancestors = append(context.Ancestors, *mastoStatus) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	children, err := p.db.StatusChildren(targetStatus) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, gtserror.NewErrorInternalError(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, status := range children { | ||||||
|  | 		if v, err := p.filter.StatusVisible(status, account); err == nil && v { | ||||||
|  | 			mastoStatus, err := p.tc.StatusToMasto(status, account) | ||||||
|  | 			if err == nil { | ||||||
|  | 				context.Ancestors = append(context.Ancestors, *mastoStatus) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sort.Slice(context.Ancestors, func(i int, j int) bool { | ||||||
|  | 		return context.Ancestors[i].ID < context.Ancestors[j].ID | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	sort.Slice(context.Descendants, func(i int, j int) bool { | ||||||
|  | 		return context.Descendants[i].ID < context.Descendants[j].ID | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	return context, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -11,11 +11,10 @@ func (f *filter) StatusHometimelineable(targetStatus *gtsmodel.Status, requestin | ||||||
| 	l := f.log.WithFields(logrus.Fields{ | 	l := f.log.WithFields(logrus.Fields{ | ||||||
| 		"func":                "StatusHometimelineable", | 		"func":                "StatusHometimelineable", | ||||||
| 		"statusID":            targetStatus.ID, | 		"statusID":            targetStatus.ID, | ||||||
| 		"requestingAccountID": requestingAccount.ID, |  | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	// status owner should always be able to see their status in their timeline so we can return early if this is the case | 	// status owner should always be able to see their status in their timeline so we can return early if this is the case | ||||||
| 	if targetStatus.AccountID == requestingAccount.ID { | 	if requestingAccount != nil && targetStatus.AccountID == requestingAccount.ID { | ||||||
| 		return true, nil | 		return true, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue