mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 11:52:24 -05:00 
			
		
		
		
	change muchos things
This commit is contained in:
		
					parent
					
						
							
								fffff93b75
							
						
					
				
			
			
				commit
				
					
						2786b5f887
					
				
			
		
					 70 changed files with 999 additions and 570 deletions
				
			
		
							
								
								
									
										72
									
								
								internal/ap/activitystreams.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								internal/ap/activitystreams.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | /* | ||||||
|  |    GoToSocial | ||||||
|  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | ||||||
|  | 
 | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU Affero General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  |    You should have received a copy of the GNU Affero General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package ap | ||||||
|  | 
 | ||||||
|  | // https://www.w3.org/TR/activitystreams-vocabulary | ||||||
|  | const ( | ||||||
|  | 	ActivityAccept          = "Accept"          // ActivityStreamsAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept | ||||||
|  | 	ActivityAdd             = "Add"             // ActivityStreamsAdd https://www.w3.org/TR/activitystreams-vocabulary/#dfn-add | ||||||
|  | 	ActivityAnnounce        = "Announce"        // ActivityStreamsAnnounce https://www.w3.org/TR/activitystreams-vocabulary/#dfn-announce | ||||||
|  | 	ActivityArrive          = "Arrive"          // ActivityStreamsArrive https://www.w3.org/TR/activitystreams-vocabulary/#dfn-arrive | ||||||
|  | 	ActivityBlock           = "Block"           // ActivityStreamsBlock https://www.w3.org/TR/activitystreams-vocabulary/#dfn-block | ||||||
|  | 	ActivityCreate          = "Create"          // ActivityStreamsCreate https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create | ||||||
|  | 	ActivityDelete          = "Delete"          // ActivityStreamsDelete https://www.w3.org/TR/activitystreams-vocabulary/#dfn-delete | ||||||
|  | 	ActivityDislike         = "Dislike"         // ActivityStreamsDislike https://www.w3.org/TR/activitystreams-vocabulary/#dfn-dislike | ||||||
|  | 	ActivityFlag            = "Flag"            // ActivityStreamsFlag https://www.w3.org/TR/activitystreams-vocabulary/#dfn-flag | ||||||
|  | 	ActivityFollow          = "Follow"          // ActivityStreamsFollow https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow | ||||||
|  | 	ActivityIgnore          = "Ignore"          // ActivityStreamsIgnore https://www.w3.org/TR/activitystreams-vocabulary/#dfn-ignore | ||||||
|  | 	ActivityInvite          = "Invite"          // ActivityStreamsInvite https://www.w3.org/TR/activitystreams-vocabulary/#dfn-invite | ||||||
|  | 	ActivityJoin            = "Join"            // ActivityStreamsJoin https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join | ||||||
|  | 	ActivityLeave           = "Leave"           // ActivityStreamsLeave https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave | ||||||
|  | 	ActivityLike            = "Like"            // ActivityStreamsLike https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like | ||||||
|  | 	ActivityListen          = "Listen"          // ActivityStreamsListen https://www.w3.org/TR/activitystreams-vocabulary/#dfn-listen | ||||||
|  | 	ActivityMove            = "Move"            // ActivityStreamsMove https://www.w3.org/TR/activitystreams-vocabulary/#dfn-move | ||||||
|  | 	ActivityOffer           = "Offer"           // ActivityStreamsOffer https://www.w3.org/TR/activitystreams-vocabulary/#dfn-offer | ||||||
|  | 	ActivityQuestion        = "Question"        // ActivityStreamsQuestion https://www.w3.org/TR/activitystreams-vocabulary/#dfn-question | ||||||
|  | 	ActivityReject          = "Reject"          // ActivityStreamsReject https://www.w3.org/TR/activitystreams-vocabulary/#dfn-reject | ||||||
|  | 	ActivityRead            = "Read"            // ActivityStreamsRead https://www.w3.org/TR/activitystreams-vocabulary/#dfn-read | ||||||
|  | 	ActivityRemove          = "Remove"          // ActivityStreamsRemove https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove | ||||||
|  | 	ActivityTentativeReject = "TentativeReject" // ActivityStreamsTentativeReject https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tentativereject | ||||||
|  | 	ActivityTentativeAccept = "TentativeAccept" // ActivityStreamsTentativeAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tentativeaccept | ||||||
|  | 	ActivityTravel          = "Travel"          // ActivityStreamsTravel https://www.w3.org/TR/activitystreams-vocabulary/#dfn-travel | ||||||
|  | 	ActivityUndo            = "Undo"            // ActivityStreamsUndo https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo | ||||||
|  | 	ActivityUpdate          = "Update"          // ActivityStreamsUpdate https://www.w3.org/TR/activitystreams-vocabulary/#dfn-update | ||||||
|  | 	ActivityView            = "View"            // ActivityStreamsView https://www.w3.org/TR/activitystreams-vocabulary/#dfn-view | ||||||
|  | 
 | ||||||
|  | 	ActorApplication  = "Application"  // ActivityStreamsApplication https://www.w3.org/TR/activitystreams-vocabulary/#dfn-application | ||||||
|  | 	ActorGroup        = "Group"        // ActivityStreamsGroup https://www.w3.org/TR/activitystreams-vocabulary/#dfn-group | ||||||
|  | 	ActorOrganization = "Organization" // ActivityStreamsOrganization https://www.w3.org/TR/activitystreams-vocabulary/#dfn-organization | ||||||
|  | 	ActorPerson       = "Person"       // ActivityStreamsPerson https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person | ||||||
|  | 	ActorService      = "Service"      // ActivityStreamsService https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service | ||||||
|  | 
 | ||||||
|  | 	ObjectArticle        = "Article"        // ActivityStreamsArticle https://www.w3.org/TR/activitystreams-vocabulary/#dfn-article | ||||||
|  | 	ObjectAudio          = "Audio"          // ActivityStreamsAudio https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audio | ||||||
|  | 	ObjectDocument       = "Document"       // ActivityStreamsDocument https://www.w3.org/TR/activitystreams-vocabulary/#dfn-document | ||||||
|  | 	ObjectEvent          = "Event"          // ActivityStreamsEvent https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event | ||||||
|  | 	ObjectImage          = "Image"          // ActivityStreamsImage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image | ||||||
|  | 	ObjectNote           = "Note"           // ActivityStreamsNote https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note | ||||||
|  | 	ObjectPage           = "Page"           // ActivityStreamsPage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-page | ||||||
|  | 	ObjectPlace          = "Place"          // ActivityStreamsPlace https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place | ||||||
|  | 	ObjectProfile        = "Profile"        // ActivityStreamsProfile https://www.w3.org/TR/activitystreams-vocabulary/#dfn-profile | ||||||
|  | 	ObjectRelationship   = "Relationship"   // ActivityStreamsRelationship https://www.w3.org/TR/activitystreams-vocabulary/#dfn-relationship | ||||||
|  | 	ObjectTombstone      = "Tombstone"      // ActivityStreamsTombstone https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone | ||||||
|  | 	ObjectVideo          = "Video"          // ActivityStreamsVideo https://www.w3.org/TR/activitystreams-vocabulary/#dfn-video | ||||||
|  | 	ObjectCollection     = "Collection"     //ActivityStreamsCollection https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection | ||||||
|  | 	ObjectCollectionPage = "CollectionPage" // ActivityStreamsCollectionPage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collectionpage | ||||||
|  | ) | ||||||
|  | @ -29,6 +29,7 @@ import ( | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | @ -113,7 +114,7 @@ func (a *adminDB) NewSignup(ctx context.Context, username string, reason string, | ||||||
| 			PrivateKey:            key, | 			PrivateKey:            key, | ||||||
| 			PublicKey:             &key.PublicKey, | 			PublicKey:             &key.PublicKey, | ||||||
| 			PublicKeyURI:          newAccountURIs.PublicKeyURI, | 			PublicKeyURI:          newAccountURIs.PublicKeyURI, | ||||||
| 			ActorType:             gtsmodel.ActivityStreamsPerson, | 			ActorType:             ap.ActorPerson, | ||||||
| 			URI:                   newAccountURIs.UserURI, | 			URI:                   newAccountURIs.UserURI, | ||||||
| 			InboxURI:              newAccountURIs.InboxURI, | 			InboxURI:              newAccountURIs.InboxURI, | ||||||
| 			OutboxURI:             newAccountURIs.OutboxURI, | 			OutboxURI:             newAccountURIs.OutboxURI, | ||||||
|  | @ -207,7 +208,7 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error { | ||||||
| 		PrivateKey:            key, | 		PrivateKey:            key, | ||||||
| 		PublicKey:             &key.PublicKey, | 		PublicKey:             &key.PublicKey, | ||||||
| 		PublicKeyURI:          newAccountURIs.PublicKeyURI, | 		PublicKeyURI:          newAccountURIs.PublicKeyURI, | ||||||
| 		ActorType:             gtsmodel.ActivityStreamsPerson, | 		ActorType:             ap.ActorPerson, | ||||||
| 		URI:                   newAccountURIs.UserURI, | 		URI:                   newAccountURIs.UserURI, | ||||||
| 		InboxURI:              newAccountURIs.InboxURI, | 		InboxURI:              newAccountURIs.InboxURI, | ||||||
| 		OutboxURI:             newAccountURIs.OutboxURI, | 		OutboxURI:             newAccountURIs.OutboxURI, | ||||||
|  |  | ||||||
|  | @ -165,19 +165,19 @@ func (d *deref) dereferenceAccountable(ctx context.Context, username string, rem | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch t.GetTypeName() { | 	switch t.GetTypeName() { | ||||||
| 	case string(gtsmodel.ActivityStreamsPerson): | 	case string(ap.ActorPerson): | ||||||
| 		p, ok := t.(vocab.ActivityStreamsPerson) | 		p, ok := t.(vocab.ActivityStreamsPerson) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceAccountable: error resolving type as activitystreams person") | 			return nil, errors.New("DereferenceAccountable: error resolving type as activitystreams person") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case string(gtsmodel.ActivityStreamsApplication): | 	case string(ap.ActorApplication): | ||||||
| 		p, ok := t.(vocab.ActivityStreamsApplication) | 		p, ok := t.(vocab.ActivityStreamsApplication) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceAccountable: error resolving type as activitystreams application") | 			return nil, errors.New("DereferenceAccountable: error resolving type as activitystreams application") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case string(gtsmodel.ActivityStreamsService): | 	case string(ap.ActorService): | ||||||
| 		p, ok := t.(vocab.ActivityStreamsService) | 		p, ok := t.(vocab.ActivityStreamsService) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceAccountable: error resolving type as activitystreams service") | 			return nil, errors.New("DereferenceAccountable: error resolving type as activitystreams service") | ||||||
|  |  | ||||||
|  | @ -28,7 +28,6 @@ import ( | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/ap" | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // DereferenceCollectionPage returns the activitystreams CollectionPage at the specified IRI, or an error if something goes wrong. | // DereferenceCollectionPage returns the activitystreams CollectionPage at the specified IRI, or an error if something goes wrong. | ||||||
|  | @ -57,7 +56,7 @@ func (d *deref) DereferenceCollectionPage(ctx context.Context, username string, | ||||||
| 		return nil, fmt.Errorf("DereferenceCollectionPage: error resolving json into ap vocab type: %s", err) | 		return nil, fmt.Errorf("DereferenceCollectionPage: error resolving json into ap vocab type: %s", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if t.GetTypeName() != gtsmodel.ActivityStreamsCollectionPage { | 	if t.GetTypeName() != ap.ObjectCollectionPage { | ||||||
| 		return nil, fmt.Errorf("DereferenceCollectionPage: type name %s not supported", t.GetTypeName()) | 		return nil, fmt.Errorf("DereferenceCollectionPage: type name %s not supported", t.GetTypeName()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -154,55 +154,55 @@ func (d *deref) dereferenceStatusable(ctx context.Context, username string, remo | ||||||
| 
 | 
 | ||||||
| 	// Article, Document, Image, Video, Note, Page, Event, Place, Mention, Profile | 	// Article, Document, Image, Video, Note, Page, Event, Place, Mention, Profile | ||||||
| 	switch t.GetTypeName() { | 	switch t.GetTypeName() { | ||||||
| 	case gtsmodel.ActivityStreamsArticle: | 	case ap.ObjectArticle: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsArticle) | 		p, ok := t.(vocab.ActivityStreamsArticle) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsArticle") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsArticle") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsDocument: | 	case ap.ObjectDocument: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsDocument) | 		p, ok := t.(vocab.ActivityStreamsDocument) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsDocument") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsDocument") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsImage: | 	case ap.ObjectImage: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsImage) | 		p, ok := t.(vocab.ActivityStreamsImage) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsImage") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsImage") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsVideo: | 	case ap.ObjectVideo: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsVideo) | 		p, ok := t.(vocab.ActivityStreamsVideo) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsVideo") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsVideo") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsNote: | 	case ap.ObjectNote: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsNote) | 		p, ok := t.(vocab.ActivityStreamsNote) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsNote") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsNote") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsPage: | 	case ap.ObjectPage: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsPage) | 		p, ok := t.(vocab.ActivityStreamsPage) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsPage") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsPage") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsEvent: | 	case ap.ObjectEvent: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsEvent) | 		p, ok := t.(vocab.ActivityStreamsEvent) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsEvent") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsEvent") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsPlace: | 	case ap.ObjectPlace: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsPlace) | 		p, ok := t.(vocab.ActivityStreamsPlace) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsPlace") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsPlace") | ||||||
| 		} | 		} | ||||||
| 		return p, nil | 		return p, nil | ||||||
| 	case gtsmodel.ActivityStreamsProfile: | 	case ap.ObjectProfile: | ||||||
| 		p, ok := t.(vocab.ActivityStreamsProfile) | 		p, ok := t.(vocab.ActivityStreamsProfile) | ||||||
| 		if !ok { | 		if !ok { | ||||||
| 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsProfile") | 			return nil, errors.New("DereferenceStatusable: error resolving type as ActivityStreamsProfile") | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing" | 	"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | @ -133,7 +134,7 @@ func (suite *StatusTestSuite) TestDereferenceSimpleStatus() { | ||||||
| 	suite.False(status.Local) | 	suite.False(status.Local) | ||||||
| 	suite.Empty(status.ContentWarning) | 	suite.Empty(status.ContentWarning) | ||||||
| 	suite.Equal(gtsmodel.VisibilityPublic, status.Visibility) | 	suite.Equal(gtsmodel.VisibilityPublic, status.Visibility) | ||||||
| 	suite.Equal(gtsmodel.ActivityStreamsNote, status.ActivityStreamsType) | 	suite.Equal(ap.ObjectNote, status.ActivityStreamsType) | ||||||
| 
 | 
 | ||||||
| 	// status should be in the database | 	// status should be in the database | ||||||
| 	dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI) | 	dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI) | ||||||
|  | @ -171,7 +172,7 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithMention() { | ||||||
| 	suite.False(status.Local) | 	suite.False(status.Local) | ||||||
| 	suite.Empty(status.ContentWarning) | 	suite.Empty(status.ContentWarning) | ||||||
| 	suite.Equal(gtsmodel.VisibilityPublic, status.Visibility) | 	suite.Equal(gtsmodel.VisibilityPublic, status.Visibility) | ||||||
| 	suite.Equal(gtsmodel.ActivityStreamsNote, status.ActivityStreamsType) | 	suite.Equal(ap.ObjectNote, status.ActivityStreamsType) | ||||||
| 
 | 
 | ||||||
| 	// status should be in the database | 	// status should be in the database | ||||||
| 	dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI) | 	dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI) | ||||||
|  |  | ||||||
|  | @ -27,8 +27,10 @@ import ( | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -67,7 +69,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA | ||||||
| 		l.Error("ACCEPT: from federator channel wasn't set on context") | 		l.Error("ACCEPT: from federator channel wasn't set on context") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator) | 	fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		l.Error("ACCEPT: from federator channel was set on context but couldn't be parsed") | 		l.Error("ACCEPT: from federator channel was set on context but couldn't be parsed") | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -99,9 +101,9 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA | ||||||
| 					return err | 					return err | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				fromFederatorChan <- gtsmodel.FromFederator{ | 				fromFederatorChan <- messages.FromFederator{ | ||||||
| 					APObjectType:     gtsmodel.ActivityStreamsFollow, | 					APObjectType:     ap.ActivityFollow, | ||||||
| 					APActivityType:   gtsmodel.ActivityStreamsAccept, | 					APActivityType:   ap.ActivityAccept, | ||||||
| 					GTSModel:         follow, | 					GTSModel:         follow, | ||||||
| 					ReceivingAccount: targetAcct, | 					ReceivingAccount: targetAcct, | ||||||
| 				} | 				} | ||||||
|  | @ -116,7 +118,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA | ||||||
| 		} | 		} | ||||||
| 		switch iter.GetType().GetTypeName() { | 		switch iter.GetType().GetTypeName() { | ||||||
| 		// we have the whole object so we can figure out what we're accepting | 		// we have the whole object so we can figure out what we're accepting | ||||||
| 		case string(gtsmodel.ActivityStreamsFollow): | 		case string(ap.ActivityFollow): | ||||||
| 			// ACCEPT FOLLOW | 			// ACCEPT FOLLOW | ||||||
| 			asFollow, ok := iter.GetType().(vocab.ActivityStreamsFollow) | 			asFollow, ok := iter.GetType().(vocab.ActivityStreamsFollow) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -136,9 +138,9 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			fromFederatorChan <- gtsmodel.FromFederator{ | 			fromFederatorChan <- messages.FromFederator{ | ||||||
| 				APObjectType:     gtsmodel.ActivityStreamsFollow, | 				APObjectType:     ap.ActivityFollow, | ||||||
| 				APActivityType:   gtsmodel.ActivityStreamsAccept, | 				APActivityType:   ap.ActivityAccept, | ||||||
| 				GTSModel:         follow, | 				GTSModel:         follow, | ||||||
| 				ReceivingAccount: targetAcct, | 				ReceivingAccount: targetAcct, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -26,7 +26,9 @@ import ( | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +67,7 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre | ||||||
| 		l.Error("ANNOUNCE: from federator channel wasn't set on context") | 		l.Error("ANNOUNCE: from federator channel wasn't set on context") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator) | 	fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		l.Error("ANNOUNCE: from federator channel was set on context but couldn't be parsed") | 		l.Error("ANNOUNCE: from federator channel was set on context but couldn't be parsed") | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -82,9 +84,9 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// it's a new announce so pass it back to the processor async for dereferencing etc | 	// it's a new announce so pass it back to the processor async for dereferencing etc | ||||||
| 	fromFederatorChan <- gtsmodel.FromFederator{ | 	fromFederatorChan <- messages.FromFederator{ | ||||||
| 		APObjectType:     gtsmodel.ActivityStreamsAnnounce, | 		APObjectType:     ap.ActivityAnnounce, | ||||||
| 		APActivityType:   gtsmodel.ActivityStreamsCreate, | 		APActivityType:   ap.ActivityCreate, | ||||||
| 		GTSModel:         boost, | 		GTSModel:         boost, | ||||||
| 		ReceivingAccount: targetAcct, | 		ReceivingAccount: targetAcct, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -27,9 +27,11 @@ import ( | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -81,14 +83,14 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error { | ||||||
| 		l.Error("CREATE: from federator channel wasn't set on context") | 		l.Error("CREATE: from federator channel wasn't set on context") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator) | 	fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		l.Error("CREATE: from federator channel was set on context but couldn't be parsed") | 		l.Error("CREATE: from federator channel was set on context but couldn't be parsed") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch asType.GetTypeName() { | 	switch asType.GetTypeName() { | ||||||
| 	case gtsmodel.ActivityStreamsCreate: | 	case ap.ActivityCreate: | ||||||
| 		// CREATE SOMETHING | 		// CREATE SOMETHING | ||||||
| 		create, ok := asType.(vocab.ActivityStreamsCreate) | 		create, ok := asType.(vocab.ActivityStreamsCreate) | ||||||
| 		if !ok { | 		if !ok { | ||||||
|  | @ -97,7 +99,7 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error { | ||||||
| 		object := create.GetActivityStreamsObject() | 		object := create.GetActivityStreamsObject() | ||||||
| 		for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() { | 		for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() { | ||||||
| 			switch objectIter.GetType().GetTypeName() { | 			switch objectIter.GetType().GetTypeName() { | ||||||
| 			case gtsmodel.ActivityStreamsNote: | 			case ap.ObjectNote: | ||||||
| 				// CREATE A NOTE | 				// CREATE A NOTE | ||||||
| 				note := objectIter.GetActivityStreamsNote() | 				note := objectIter.GetActivityStreamsNote() | ||||||
| 				status, err := f.typeConverter.ASStatusToStatus(ctx, note) | 				status, err := f.typeConverter.ASStatusToStatus(ctx, note) | ||||||
|  | @ -122,15 +124,15 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error { | ||||||
| 					return fmt.Errorf("CREATE: database error inserting status: %s", err) | 					return fmt.Errorf("CREATE: database error inserting status: %s", err) | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				fromFederatorChan <- gtsmodel.FromFederator{ | 				fromFederatorChan <- messages.FromFederator{ | ||||||
| 					APObjectType:     gtsmodel.ActivityStreamsNote, | 					APObjectType:     ap.ObjectNote, | ||||||
| 					APActivityType:   gtsmodel.ActivityStreamsCreate, | 					APActivityType:   ap.ActivityCreate, | ||||||
| 					GTSModel:         status, | 					GTSModel:         status, | ||||||
| 					ReceivingAccount: targetAcct, | 					ReceivingAccount: targetAcct, | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsFollow: | 	case ap.ActivityFollow: | ||||||
| 		// FOLLOW SOMETHING | 		// FOLLOW SOMETHING | ||||||
| 		follow, ok := asType.(vocab.ActivityStreamsFollow) | 		follow, ok := asType.(vocab.ActivityStreamsFollow) | ||||||
| 		if !ok { | 		if !ok { | ||||||
|  | @ -152,13 +154,13 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error { | ||||||
| 			return fmt.Errorf("CREATE: database error inserting follow request: %s", err) | 			return fmt.Errorf("CREATE: database error inserting follow request: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		fromFederatorChan <- gtsmodel.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     gtsmodel.ActivityStreamsFollow, | 			APObjectType:     ap.ActivityFollow, | ||||||
| 			APActivityType:   gtsmodel.ActivityStreamsCreate, | 			APActivityType:   ap.ActivityCreate, | ||||||
| 			GTSModel:         followRequest, | 			GTSModel:         followRequest, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsLike: | 	case ap.ActivityLike: | ||||||
| 		// LIKE SOMETHING | 		// LIKE SOMETHING | ||||||
| 		like, ok := asType.(vocab.ActivityStreamsLike) | 		like, ok := asType.(vocab.ActivityStreamsLike) | ||||||
| 		if !ok { | 		if !ok { | ||||||
|  | @ -180,13 +182,13 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error { | ||||||
| 			return fmt.Errorf("CREATE: database error inserting fave: %s", err) | 			return fmt.Errorf("CREATE: database error inserting fave: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		fromFederatorChan <- gtsmodel.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     gtsmodel.ActivityStreamsLike, | 			APObjectType:     ap.ActivityLike, | ||||||
| 			APActivityType:   gtsmodel.ActivityStreamsCreate, | 			APActivityType:   ap.ActivityCreate, | ||||||
| 			GTSModel:         fave, | 			GTSModel:         fave, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsBlock: | 	case ap.ActivityBlock: | ||||||
| 		// BLOCK SOMETHING | 		// BLOCK SOMETHING | ||||||
| 		blockable, ok := asType.(vocab.ActivityStreamsBlock) | 		blockable, ok := asType.(vocab.ActivityStreamsBlock) | ||||||
| 		if !ok { | 		if !ok { | ||||||
|  | @ -208,9 +210,9 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error { | ||||||
| 			return fmt.Errorf("CREATE: database error inserting block: %s", err) | 			return fmt.Errorf("CREATE: database error inserting block: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		fromFederatorChan <- gtsmodel.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     gtsmodel.ActivityStreamsBlock, | 			APObjectType:     ap.ActivityBlock, | ||||||
| 			APActivityType:   gtsmodel.ActivityStreamsCreate, | 			APActivityType:   ap.ActivityCreate, | ||||||
| 			GTSModel:         block, | 			GTSModel:         block, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -24,7 +24,9 @@ import ( | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -61,7 +63,7 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error { | ||||||
| 		l.Error("DELETE: from federator channel wasn't set on context") | 		l.Error("DELETE: from federator channel wasn't set on context") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator) | 	fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		l.Error("DELETE: from federator channel was set on context but couldn't be parsed") | 		l.Error("DELETE: from federator channel was set on context but couldn't be parsed") | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -76,9 +78,9 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error { | ||||||
| 		if err := f.db.DeleteByID(ctx, s.ID, >smodel.Status{}); err != nil { | 		if err := f.db.DeleteByID(ctx, s.ID, >smodel.Status{}); err != nil { | ||||||
| 			return fmt.Errorf("DELETE: err deleting status: %s", err) | 			return fmt.Errorf("DELETE: err deleting status: %s", err) | ||||||
| 		} | 		} | ||||||
| 		fromFederatorChan <- gtsmodel.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     gtsmodel.ActivityStreamsNote, | 			APObjectType:     ap.ObjectNote, | ||||||
| 			APActivityType:   gtsmodel.ActivityStreamsDelete, | 			APActivityType:   ap.ActivityDelete, | ||||||
| 			GTSModel:         s, | 			GTSModel:         s, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
|  | @ -91,9 +93,9 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error { | ||||||
| 		if err := f.db.DeleteByID(ctx, a.ID, >smodel.Account{}); err != nil { | 		if err := f.db.DeleteByID(ctx, a.ID, >smodel.Account{}); err != nil { | ||||||
| 			return fmt.Errorf("DELETE: err deleting account: %s", err) | 			return fmt.Errorf("DELETE: err deleting account: %s", err) | ||||||
| 		} | 		} | ||||||
| 		fromFederatorChan <- gtsmodel.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     gtsmodel.ActivityStreamsProfile, | 			APObjectType:     ap.ObjectProfile, | ||||||
| 			APActivityType:   gtsmodel.ActivityStreamsDelete, | 			APActivityType:   ap.ActivityDelete, | ||||||
| 			GTSModel:         a, | 			GTSModel:         a, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ( | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
|  | @ -72,7 +73,7 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		switch iter.GetType().GetTypeName() { | 		switch iter.GetType().GetTypeName() { | ||||||
| 		case string(gtsmodel.ActivityStreamsFollow): | 		case string(ap.ActivityFollow): | ||||||
| 			// UNDO FOLLOW | 			// UNDO FOLLOW | ||||||
| 			ASFollow, ok := iter.GetType().(vocab.ActivityStreamsFollow) | 			ASFollow, ok := iter.GetType().(vocab.ActivityStreamsFollow) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -101,11 +102,11 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo) | ||||||
| 			} | 			} | ||||||
| 			l.Debug("follow undone") | 			l.Debug("follow undone") | ||||||
| 			return nil | 			return nil | ||||||
| 		case string(gtsmodel.ActivityStreamsLike): | 		case string(ap.ActivityLike): | ||||||
| 			// UNDO LIKE | 			// UNDO LIKE | ||||||
| 		case string(gtsmodel.ActivityStreamsAnnounce): | 		case string(ap.ActivityAnnounce): | ||||||
| 			// UNDO BOOST/REBLOG/ANNOUNCE | 			// UNDO BOOST/REBLOG/ANNOUNCE | ||||||
| 		case string(gtsmodel.ActivityStreamsBlock): | 		case string(ap.ActivityBlock): | ||||||
| 			// UNDO BLOCK | 			// UNDO BLOCK | ||||||
| 			ASBlock, ok := iter.GetType().(vocab.ActivityStreamsBlock) | 			ASBlock, ok := iter.GetType().(vocab.ActivityStreamsBlock) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ import ( | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/ap" | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -84,50 +85,50 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { | ||||||
| 	if fromFederatorChanI == nil { | 	if fromFederatorChanI == nil { | ||||||
| 		l.Error("UPDATE: from federator channel wasn't set on context") | 		l.Error("UPDATE: from federator channel wasn't set on context") | ||||||
| 	} | 	} | ||||||
| 	fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator) | 	fromFederatorChan, ok := fromFederatorChanI.(chan messages.FromFederator) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		l.Error("UPDATE: from federator channel was set on context but couldn't be parsed") | 		l.Error("UPDATE: from federator channel was set on context but couldn't be parsed") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	typeName := asType.GetTypeName() | 	typeName := asType.GetTypeName() | ||||||
| 	if typeName == gtsmodel.ActivityStreamsApplication || | 	if typeName == ap.ActorApplication || | ||||||
| 		typeName == gtsmodel.ActivityStreamsGroup || | 		typeName == ap.ActorGroup || | ||||||
| 		typeName == gtsmodel.ActivityStreamsOrganization || | 		typeName == ap.ActorOrganization || | ||||||
| 		typeName == gtsmodel.ActivityStreamsPerson || | 		typeName == ap.ActorPerson || | ||||||
| 		typeName == gtsmodel.ActivityStreamsService { | 		typeName == ap.ActorService { | ||||||
| 		// it's an UPDATE to some kind of account | 		// it's an UPDATE to some kind of account | ||||||
| 		var accountable ap.Accountable | 		var accountable ap.Accountable | ||||||
| 
 | 
 | ||||||
| 		switch asType.GetTypeName() { | 		switch asType.GetTypeName() { | ||||||
| 		case gtsmodel.ActivityStreamsApplication: | 		case ap.ActorApplication: | ||||||
| 			l.Debug("got update for APPLICATION") | 			l.Debug("got update for APPLICATION") | ||||||
| 			i, ok := asType.(vocab.ActivityStreamsApplication) | 			i, ok := asType.(vocab.ActivityStreamsApplication) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("UPDATE: could not convert type to application") | 				return errors.New("UPDATE: could not convert type to application") | ||||||
| 			} | 			} | ||||||
| 			accountable = i | 			accountable = i | ||||||
| 		case gtsmodel.ActivityStreamsGroup: | 		case ap.ActorGroup: | ||||||
| 			l.Debug("got update for GROUP") | 			l.Debug("got update for GROUP") | ||||||
| 			i, ok := asType.(vocab.ActivityStreamsGroup) | 			i, ok := asType.(vocab.ActivityStreamsGroup) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("UPDATE: could not convert type to group") | 				return errors.New("UPDATE: could not convert type to group") | ||||||
| 			} | 			} | ||||||
| 			accountable = i | 			accountable = i | ||||||
| 		case gtsmodel.ActivityStreamsOrganization: | 		case ap.ActorOrganization: | ||||||
| 			l.Debug("got update for ORGANIZATION") | 			l.Debug("got update for ORGANIZATION") | ||||||
| 			i, ok := asType.(vocab.ActivityStreamsOrganization) | 			i, ok := asType.(vocab.ActivityStreamsOrganization) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("UPDATE: could not convert type to organization") | 				return errors.New("UPDATE: could not convert type to organization") | ||||||
| 			} | 			} | ||||||
| 			accountable = i | 			accountable = i | ||||||
| 		case gtsmodel.ActivityStreamsPerson: | 		case ap.ActorPerson: | ||||||
| 			l.Debug("got update for PERSON") | 			l.Debug("got update for PERSON") | ||||||
| 			i, ok := asType.(vocab.ActivityStreamsPerson) | 			i, ok := asType.(vocab.ActivityStreamsPerson) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("UPDATE: could not convert type to person") | 				return errors.New("UPDATE: could not convert type to person") | ||||||
| 			} | 			} | ||||||
| 			accountable = i | 			accountable = i | ||||||
| 		case gtsmodel.ActivityStreamsService: | 		case ap.ActorService: | ||||||
| 			l.Debug("got update for SERVICE") | 			l.Debug("got update for SERVICE") | ||||||
| 			i, ok := asType.(vocab.ActivityStreamsService) | 			i, ok := asType.(vocab.ActivityStreamsService) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -157,9 +158,9 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { | ||||||
| 			return fmt.Errorf("UPDATE: database error inserting updated account: %s", err) | 			return fmt.Errorf("UPDATE: database error inserting updated account: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		fromFederatorChan <- gtsmodel.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     gtsmodel.ActivityStreamsProfile, | 			APObjectType:     ap.ObjectProfile, | ||||||
| 			APActivityType:   gtsmodel.ActivityStreamsUpdate, | 			APActivityType:   ap.ActivityUpdate, | ||||||
| 			GTSModel:         updatedAcct, | 			GTSModel:         updatedAcct, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ import ( | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | @ -78,7 +79,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 	l.Debugf("received NEWID request for asType %s", string(b)) | 	l.Debugf("received NEWID request for asType %s", string(b)) | ||||||
| 
 | 
 | ||||||
| 	switch t.GetTypeName() { | 	switch t.GetTypeName() { | ||||||
| 	case gtsmodel.ActivityStreamsFollow: | 	case ap.ActivityFollow: | ||||||
| 		// FOLLOW | 		// FOLLOW | ||||||
| 		// ID might already be set on a follow we've created, so check it here and return it if it is | 		// ID might already be set on a follow we've created, so check it here and return it if it is | ||||||
| 		follow, ok := t.(vocab.ActivityStreamsFollow) | 		follow, ok := t.(vocab.ActivityStreamsFollow) | ||||||
|  | @ -108,7 +109,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsNote: | 	case ap.ObjectNote: | ||||||
| 		// NOTE aka STATUS | 		// NOTE aka STATUS | ||||||
| 		// ID might already be set on a note we've created, so check it here and return it if it is | 		// ID might already be set on a note we've created, so check it here and return it if it is | ||||||
| 		note, ok := t.(vocab.ActivityStreamsNote) | 		note, ok := t.(vocab.ActivityStreamsNote) | ||||||
|  | @ -121,7 +122,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 				return idProp.GetIRI(), nil | 				return idProp.GetIRI(), nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsLike: | 	case ap.ActivityLike: | ||||||
| 		// LIKE aka FAVE | 		// LIKE aka FAVE | ||||||
| 		// ID might already be set on a fave we've created, so check it here and return it if it is | 		// ID might already be set on a fave we've created, so check it here and return it if it is | ||||||
| 		fave, ok := t.(vocab.ActivityStreamsLike) | 		fave, ok := t.(vocab.ActivityStreamsLike) | ||||||
|  | @ -134,7 +135,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 				return idProp.GetIRI(), nil | 				return idProp.GetIRI(), nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsAnnounce: | 	case ap.ActivityAnnounce: | ||||||
| 		// ANNOUNCE aka BOOST | 		// ANNOUNCE aka BOOST | ||||||
| 		// ID might already be set on an announce we've created, so check it here and return it if it is | 		// ID might already be set on an announce we've created, so check it here and return it if it is | ||||||
| 		announce, ok := t.(vocab.ActivityStreamsAnnounce) | 		announce, ok := t.(vocab.ActivityStreamsAnnounce) | ||||||
|  | @ -147,7 +148,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 				return idProp.GetIRI(), nil | 				return idProp.GetIRI(), nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsUpdate: | 	case ap.ActivityUpdate: | ||||||
| 		// UPDATE | 		// UPDATE | ||||||
| 		// ID might already be set on an update we've created, so check it here and return it if it is | 		// ID might already be set on an update we've created, so check it here and return it if it is | ||||||
| 		update, ok := t.(vocab.ActivityStreamsUpdate) | 		update, ok := t.(vocab.ActivityStreamsUpdate) | ||||||
|  | @ -160,7 +161,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 				return idProp.GetIRI(), nil | 				return idProp.GetIRI(), nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsBlock: | 	case ap.ActivityBlock: | ||||||
| 		// BLOCK | 		// BLOCK | ||||||
| 		// ID might already be set on a block we've created, so check it here and return it if it is | 		// ID might already be set on a block we've created, so check it here and return it if it is | ||||||
| 		block, ok := t.(vocab.ActivityStreamsBlock) | 		block, ok := t.(vocab.ActivityStreamsBlock) | ||||||
|  | @ -173,7 +174,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, | ||||||
| 				return idProp.GetIRI(), nil | 				return idProp.GetIRI(), nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsUndo: | 	case ap.ActivityUndo: | ||||||
| 		// UNDO | 		// UNDO | ||||||
| 		// ID might already be set on an undo we've created, so check it here and return it if it is | 		// ID might already be set on an undo we've created, so check it here and return it if it is | ||||||
| 		undo, ok := t.(vocab.ActivityStreamsUndo) | 		undo, ok := t.(vocab.ActivityStreamsUndo) | ||||||
|  |  | ||||||
|  | @ -1,122 +0,0 @@ | ||||||
| /* |  | ||||||
|    GoToSocial |  | ||||||
|    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org |  | ||||||
| 
 |  | ||||||
|    This program is free software: you can redistribute it and/or modify |  | ||||||
|    it under the terms of the GNU Affero General Public License as published by |  | ||||||
|    the Free Software Foundation, either version 3 of the License, or |  | ||||||
|    (at your option) any later version. |  | ||||||
| 
 |  | ||||||
|    This program is distributed in the hope that it will be useful, |  | ||||||
|    but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|    GNU Affero General Public License for more details. |  | ||||||
| 
 |  | ||||||
|    You should have received a copy of the GNU Affero General Public License |  | ||||||
|    along with this program.  If not, see <http://www.gnu.org/licenses/>. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| package gtsmodel |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	// ActivityStreamsArticle https://www.w3.org/TR/activitystreams-vocabulary/#dfn-article |  | ||||||
| 	ActivityStreamsArticle = "Article" |  | ||||||
| 	// ActivityStreamsAudio https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audio |  | ||||||
| 	ActivityStreamsAudio = "Audio" |  | ||||||
| 	// ActivityStreamsDocument https://www.w3.org/TR/activitystreams-vocabulary/#dfn-document |  | ||||||
| 	ActivityStreamsDocument = "Document" |  | ||||||
| 	// ActivityStreamsEvent https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event |  | ||||||
| 	ActivityStreamsEvent = "Event" |  | ||||||
| 	// ActivityStreamsImage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image |  | ||||||
| 	ActivityStreamsImage = "Image" |  | ||||||
| 	// ActivityStreamsNote https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note |  | ||||||
| 	ActivityStreamsNote = "Note" |  | ||||||
| 	// ActivityStreamsPage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-page |  | ||||||
| 	ActivityStreamsPage = "Page" |  | ||||||
| 	// ActivityStreamsPlace https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place |  | ||||||
| 	ActivityStreamsPlace = "Place" |  | ||||||
| 	// ActivityStreamsProfile https://www.w3.org/TR/activitystreams-vocabulary/#dfn-profile |  | ||||||
| 	ActivityStreamsProfile = "Profile" |  | ||||||
| 	// ActivityStreamsRelationship https://www.w3.org/TR/activitystreams-vocabulary/#dfn-relationship |  | ||||||
| 	ActivityStreamsRelationship = "Relationship" |  | ||||||
| 	// ActivityStreamsTombstone https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone |  | ||||||
| 	ActivityStreamsTombstone = "Tombstone" |  | ||||||
| 	// ActivityStreamsVideo https://www.w3.org/TR/activitystreams-vocabulary/#dfn-video |  | ||||||
| 	ActivityStreamsVideo = "Video" |  | ||||||
| 	//ActivityStreamsCollection https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection |  | ||||||
| 	ActivityStreamsCollection = "Collection" |  | ||||||
| 	// ActivityStreamsCollectionPage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collectionpage |  | ||||||
| 	ActivityStreamsCollectionPage = "CollectionPage" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	// ActivityStreamsApplication https://www.w3.org/TR/activitystreams-vocabulary/#dfn-application |  | ||||||
| 	ActivityStreamsApplication = "Application" |  | ||||||
| 	// ActivityStreamsGroup https://www.w3.org/TR/activitystreams-vocabulary/#dfn-group |  | ||||||
| 	ActivityStreamsGroup = "Group" |  | ||||||
| 	// ActivityStreamsOrganization https://www.w3.org/TR/activitystreams-vocabulary/#dfn-organization |  | ||||||
| 	ActivityStreamsOrganization = "Organization" |  | ||||||
| 	// ActivityStreamsPerson https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person |  | ||||||
| 	ActivityStreamsPerson = "Person" |  | ||||||
| 	// ActivityStreamsService https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service |  | ||||||
| 	ActivityStreamsService = "Service" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( |  | ||||||
| 	// ActivityStreamsAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept |  | ||||||
| 	ActivityStreamsAccept = "Accept" |  | ||||||
| 	// ActivityStreamsAdd https://www.w3.org/TR/activitystreams-vocabulary/#dfn-add |  | ||||||
| 	ActivityStreamsAdd = "Add" |  | ||||||
| 	// ActivityStreamsAnnounce https://www.w3.org/TR/activitystreams-vocabulary/#dfn-announce |  | ||||||
| 	ActivityStreamsAnnounce = "Announce" |  | ||||||
| 	// ActivityStreamsArrive https://www.w3.org/TR/activitystreams-vocabulary/#dfn-arrive |  | ||||||
| 	ActivityStreamsArrive = "Arrive" |  | ||||||
| 	// ActivityStreamsBlock https://www.w3.org/TR/activitystreams-vocabulary/#dfn-block |  | ||||||
| 	ActivityStreamsBlock = "Block" |  | ||||||
| 	// ActivityStreamsCreate https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create |  | ||||||
| 	ActivityStreamsCreate = "Create" |  | ||||||
| 	// ActivityStreamsDelete https://www.w3.org/TR/activitystreams-vocabulary/#dfn-delete |  | ||||||
| 	ActivityStreamsDelete = "Delete" |  | ||||||
| 	// ActivityStreamsDislike https://www.w3.org/TR/activitystreams-vocabulary/#dfn-dislike |  | ||||||
| 	ActivityStreamsDislike = "Dislike" |  | ||||||
| 	// ActivityStreamsFlag https://www.w3.org/TR/activitystreams-vocabulary/#dfn-flag |  | ||||||
| 	ActivityStreamsFlag = "Flag" |  | ||||||
| 	// ActivityStreamsFollow https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow |  | ||||||
| 	ActivityStreamsFollow = "Follow" |  | ||||||
| 	// ActivityStreamsIgnore https://www.w3.org/TR/activitystreams-vocabulary/#dfn-ignore |  | ||||||
| 	ActivityStreamsIgnore = "Ignore" |  | ||||||
| 	// ActivityStreamsInvite https://www.w3.org/TR/activitystreams-vocabulary/#dfn-invite |  | ||||||
| 	ActivityStreamsInvite = "Invite" |  | ||||||
| 	// ActivityStreamsJoin https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join |  | ||||||
| 	ActivityStreamsJoin = "Join" |  | ||||||
| 	// ActivityStreamsLeave https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave |  | ||||||
| 	ActivityStreamsLeave = "Leave" |  | ||||||
| 	// ActivityStreamsLike https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like |  | ||||||
| 	ActivityStreamsLike = "Like" |  | ||||||
| 	// ActivityStreamsListen https://www.w3.org/TR/activitystreams-vocabulary/#dfn-listen |  | ||||||
| 	ActivityStreamsListen = "Listen" |  | ||||||
| 	// ActivityStreamsMove https://www.w3.org/TR/activitystreams-vocabulary/#dfn-move |  | ||||||
| 	ActivityStreamsMove = "Move" |  | ||||||
| 	// ActivityStreamsOffer https://www.w3.org/TR/activitystreams-vocabulary/#dfn-offer |  | ||||||
| 	ActivityStreamsOffer = "Offer" |  | ||||||
| 	// ActivityStreamsQuestion https://www.w3.org/TR/activitystreams-vocabulary/#dfn-question |  | ||||||
| 	ActivityStreamsQuestion = "Question" |  | ||||||
| 	// ActivityStreamsReject https://www.w3.org/TR/activitystreams-vocabulary/#dfn-reject |  | ||||||
| 	ActivityStreamsReject = "Reject" |  | ||||||
| 	// ActivityStreamsRead https://www.w3.org/TR/activitystreams-vocabulary/#dfn-read |  | ||||||
| 	ActivityStreamsRead = "Read" |  | ||||||
| 	// ActivityStreamsRemove https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove |  | ||||||
| 	ActivityStreamsRemove = "Remove" |  | ||||||
| 	// ActivityStreamsTentativeReject https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tentativereject |  | ||||||
| 	ActivityStreamsTentativeReject = "TentativeReject" |  | ||||||
| 	// ActivityStreamsTentativeAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tentativeaccept |  | ||||||
| 	ActivityStreamsTentativeAccept = "TentativeAccept" |  | ||||||
| 	// ActivityStreamsTravel https://www.w3.org/TR/activitystreams-vocabulary/#dfn-travel |  | ||||||
| 	ActivityStreamsTravel = "Travel" |  | ||||||
| 	// ActivityStreamsUndo https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo |  | ||||||
| 	ActivityStreamsUndo = "Undo" |  | ||||||
| 	// ActivityStreamsUpdate https://www.w3.org/TR/activitystreams-vocabulary/#dfn-update |  | ||||||
| 	ActivityStreamsUpdate = "Update" |  | ||||||
| 	// ActivityStreamsView https://www.w3.org/TR/activitystreams-vocabulary/#dfn-view |  | ||||||
| 	ActivityStreamsView = "View" |  | ||||||
| ) |  | ||||||
|  | @ -21,20 +21,12 @@ package gtsmodel | ||||||
| // Application represents an application that can perform actions on behalf of a user. | // Application represents an application that can perform actions on behalf of a user. | ||||||
| // It is used to authorize tokens etc, and is associated with an oauth client id in the database. | // It is used to authorize tokens etc, and is associated with an oauth client id in the database. | ||||||
| type Application struct { | type Application struct { | ||||||
| 	// id of this application in the db | 	ID           string `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull"` // id of this application in the db | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull"` | 	Name         string `validate:"required" bun:",nullzero,notnull"`                      // name of the application given when it was created (eg., 'tusky') | ||||||
| 	// name of the application given when it was created (eg., 'tusky') | 	Website      string `validate:"omitempty,url" bun:",nullzero"`                         // website for the application given when it was created (eg., 'https://tusky.app') | ||||||
| 	Name string `bun:",nullzero"` | 	RedirectURI  string `validate:"required" bun:",nullzero,notnull"`                      // redirect uri requested by the application for oauth2 flow | ||||||
| 	// website for the application given when it was created (eg., 'https://tusky.app') | 	ClientID     string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`           // id of the associated oauth client entity in the db | ||||||
| 	Website string `bun:",nullzero"` | 	ClientSecret string `validate:"required,uuid" bun:",nullzero,notnull"`                 // secret of the associated oauth client entity in the db | ||||||
| 	// redirect uri requested by the application for oauth2 flow | 	Scopes       string `validate:"required" bun:",nullzero,default:'read'"`               // scopes requested when this app was created | ||||||
| 	RedirectURI string `bun:",nullzero"` | 	VapidKey     string `validate:"-" bun:",nullzero"`                                     // a vapid key generated for this app when it was created | ||||||
| 	// id of the associated oauth client entity in the db |  | ||||||
| 	ClientID string `bun:"type:CHAR(26),nullzero"` |  | ||||||
| 	// secret of the associated oauth client entity in the db |  | ||||||
| 	ClientSecret string `bun:",nullzero"` |  | ||||||
| 	// scopes requested when this app was created |  | ||||||
| 	Scopes string `bun:",nullzero"` |  | ||||||
| 	// a vapid key generated for this app when it was created |  | ||||||
| 	VapidKey string `bun:",nullzero"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,18 +4,12 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // Block refers to the blocking of one account by another. | // Block refers to the blocking of one account by another. | ||||||
| type Block struct { | type Block struct { | ||||||
| 	// id of this block in the database | 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull"` | 	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	// When was this block created | 	UpdatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	URI             string    `validate:"required,url" bun:",notnull,nullzero,unique"`                  // ActivityPub uri of this block. | ||||||
| 	// When was this block updated | 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull"` // Who does this block originate from? | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to accountID | ||||||
| 	// Who created this block? | 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull"` // Who is the target of this block ? | ||||||
| 	AccountID string   `bun:"type:CHAR(26),notnull"` | 	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to targetAccountID | ||||||
| 	Account   *Account `bun:"rel:belongs-to"` |  | ||||||
| 	// Who is targeted by this block? |  | ||||||
| 	TargetAccountID string   `bun:"type:CHAR(26),notnull"` |  | ||||||
| 	TargetAccount   *Account `bun:"rel:belongs-to"` |  | ||||||
| 	// Activitypub URI for this block |  | ||||||
| 	URI string `bun:",notnull"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,23 +22,14 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // DomainBlock represents a federation block against a particular domain | // DomainBlock represents a federation block against a particular domain | ||||||
| type DomainBlock struct { | type DomainBlock struct { | ||||||
| 	// ID of this block in the database | 	ID                 string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull,unique"` | 	CreatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	// blocked domain | 	UpdatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	Domain string `bun:",pk,notnull,unique"` | 	Domain             string    `validate:"required,fqdn" bun:",nullzero,notnull"`                        // domain to block. Eg. 'whatever.com' | ||||||
| 	// When was this block created | 	CreatedByAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // Account ID of the creator of this block | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	CreatedByAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to createdByAccountID | ||||||
| 	// When was this block updated | 	PrivateComment     string    `validate:"-" bun:",nullzero"`                                            // Private comment on this block, viewable to admins | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	PublicComment      string    `validate:"-" bun:",nullzero"`                                            // Public comment on this block, viewable (optionally) by everyone | ||||||
| 	// Account ID of the creator of this block | 	Obfuscate          bool      `validate:"-" bun:",nullzero,default:false"`                              // whether the domain name should appear obfuscated when displaying it publicly | ||||||
| 	CreatedByAccountID string   `bun:"type:CHAR(26),notnull"` | 	SubscriptionID     string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                  // if this block was created through a subscription, what's the subscription ID? | ||||||
| 	CreatedByAccount   *Account `bun:"rel:belongs-to"` |  | ||||||
| 	// Private comment on this block, viewable to admins |  | ||||||
| 	PrivateComment string `bun:",nullzero"` |  | ||||||
| 	// Public comment on this block, viewable (optionally) by everyone |  | ||||||
| 	PublicComment string `bun:",nullzero"` |  | ||||||
| 	// whether the domain name should appear obfuscated when displaying it publicly |  | ||||||
| 	Obfuscate bool |  | ||||||
| 	// if this block was created through a subscription, what's the subscription ID? |  | ||||||
| 	SubscriptionID string `bun:"type:CHAR(26),nullzero"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,15 +22,10 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // EmailDomainBlock represents a domain that the server should automatically reject sign-up requests from. | // EmailDomainBlock represents a domain that the server should automatically reject sign-up requests from. | ||||||
| type EmailDomainBlock struct { | type EmailDomainBlock struct { | ||||||
| 	// ID of this block in the database | 	ID                 string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull,unique"` | 	CreatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	// Email domain to block. Eg. 'gmail.com' or 'hotmail.com' | 	UpdatedAt          time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	Domain string `bun:",notnull"` | 	Domain             string    `validate:"required,fqdn" bun:",nullzero,notnull"`                        // Email domain to block. Eg. 'gmail.com' or 'hotmail.com' | ||||||
| 	// When was this block created | 	CreatedByAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // Account ID of the creator of this block | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	CreatedByAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to createdByAccountID | ||||||
| 	// When was this block updated |  | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` |  | ||||||
| 	// Account ID of the creator of this block |  | ||||||
| 	CreatedByAccountID string   `bun:"type:CHAR(26),notnull"` |  | ||||||
| 	CreatedByAccount   *Account `bun:"rel:belongs-to"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,56 +22,24 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // Emoji represents a custom emoji that's been uploaded through the admin UI, and is useable by instance denizens. | // Emoji represents a custom emoji that's been uploaded through the admin UI, and is useable by instance denizens. | ||||||
| type Emoji struct { | type Emoji struct { | ||||||
| 	// database ID of this emoji | 	ID                     string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull"` | 	CreatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                         // when was item created | ||||||
| 	// String shortcode for this emoji -- the part that's between colons. This should be lowercase a-z_ | 	UpdatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                         // when was item last updated | ||||||
| 	// eg., 'blob_hug' 'purple_heart' Must be unique with domain. | 	Shortcode              string    `validate:"required" bun:",notnull,unique:shortcodedomain"`                                              // String shortcode for this emoji -- the part that's between colons. This should be lowercase a-z_  eg., 'blob_hug' 'purple_heart' Must be unique with domain. | ||||||
| 	Shortcode string `bun:",notnull,unique:shortcodedomain"` | 	Domain                 string    `validate:"omitempty,fqdn" bun:",notnull,default:'',unique:shortcodedomain"`                             // Origin domain of this emoji, eg 'example.org', 'queer.party'. empty string for local emojis. | ||||||
| 	// Origin domain of this emoji, eg 'example.org', 'queer.party'. empty string for local emojis. | 	ImageRemoteURL         string    `validate:"required_without=ImageURL,omitempty,url" bun:",nullzero"`                                     // Where can this emoji be retrieved remotely? Null for local emojis. | ||||||
| 	Domain string `bun:",notnull,default:'',unique:shortcodedomain"` | 	ImageStaticRemoteURL   string    `validate:"required_without=ImageStaticURL,omitempty,url" bun:",nullzero"`                               // Where can a static / non-animated version of this emoji be retrieved remotely? Null for local emojis. | ||||||
| 	// When was this emoji created. Must be unique with shortcode. | 	ImageURL               string    `validate:"required_without=ImageRemoteURL,required_without=Domain,omitempty,url" bun:",nullzero"`       // Where can this emoji be retrieved from the local server? Null for remote emojis. | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	ImageStaticURL         string    `validate:"required_without=ImageStaticRemoteURL,required_without=Domain,omitempty,url" bun:",nullzero"` // Where can a static version of this emoji be retrieved from the local server? Null for remote emojis. | ||||||
| 	// When was this emoji updated | 	ImagePath              string    `validate:"required,file" bun:",nullzero,notnull"`                                                       // Path of the emoji image in the server storage system. | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	ImageStaticPath        string    `validate:"required,file" bun:",nullzero,notnull"`                                                       // Path of a static version of the emoji image in the server storage system | ||||||
| 	// Where can this emoji be retrieved remotely? Null for local emojis. | 	ImageContentType       string    `validate:"required" bun:",nullzero,notnull"`                                                            // MIME content type of the emoji image | ||||||
| 	// For remote emojis, it'll be something like: | 	ImageStaticContentType string    `validate:"required" bun:",nullzero,notnull"`                                                            // MIME content type of the static version of the emoji image. | ||||||
| 	// https://hackers.town/system/custom_emojis/images/000/049/842/original/1b74481204feabfd.png | 	ImageFileSize          int       `validate:"required,min=1" bun:",nullzero,notnull"`                                                      // Size of the emoji image file in bytes, for serving purposes. | ||||||
| 	ImageRemoteURL string `bun:",nullzero"` | 	ImageStaticFileSize    int       `validate:"required,min=1" bun:",nullzero,notnull"`                                                      // Size of the static version of the emoji image file in bytes, for serving purposes. | ||||||
| 	// Where can a static / non-animated version of this emoji be retrieved remotely? Null for local emojis. | 	ImageUpdatedAt         time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                         // When was the emoji image last updated? | ||||||
| 	// For remote emojis, it'll be something like: | 	Disabled               bool      `validate:"-" bun:",notnull,default:false"`                                                              // Has a moderation action disabled this emoji from being shown? | ||||||
| 	// https://hackers.town/system/custom_emojis/images/000/049/842/static/1b74481204feabfd.png | 	URI                    string    `validate:"url" bun:",nullzero,notnull,unique"`                                                          // ActivityPub uri of this emoji. Something like 'https://example.org/emojis/1234' | ||||||
| 	ImageStaticRemoteURL string `bun:",nullzero"` | 	VisibleInPicker        bool      `validate:"-" bun:",notnull,default:true"`                                                               // Is this emoji visible in the admin emoji picker? | ||||||
| 	// Where can this emoji be retrieved from the local server? Null for remote emojis. | 	CategoryID             string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                                 // In which emoji category is this emoji visible? | ||||||
| 	// Assuming our server is hosted at 'example.org', this will be something like: |  | ||||||
| 	// 'https://example.org/fileserver/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/original/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png' |  | ||||||
| 	ImageURL string `bun:",nullzero"` |  | ||||||
| 	// Where can a static version of this emoji be retrieved from the local server? Null for remote emojis. |  | ||||||
| 	// Assuming our server is hosted at 'example.org', this will be something like: |  | ||||||
| 	// 'https://example.org/fileserver/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/small/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png' |  | ||||||
| 	ImageStaticURL string `bun:",nullzero"` |  | ||||||
| 	// Path of the emoji image in the server storage system. Will be something like: |  | ||||||
| 	// '/gotosocial/storage/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/original/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png' |  | ||||||
| 	ImagePath string `bun:",notnull"` |  | ||||||
| 	// Path of a static version of the emoji image in the server storage system. Will be something like: |  | ||||||
| 	// '/gotosocial/storage/6339820e-ef65-4166-a262-5a9f46adb1a7/emoji/small/bfa6c9c5-6c25-4ea4-98b4-d78b8126fb52.png' |  | ||||||
| 	ImageStaticPath string `bun:",notnull"` |  | ||||||
| 	// MIME content type of the emoji image |  | ||||||
| 	// Probably "image/png" |  | ||||||
| 	ImageContentType string `bun:",notnull"` |  | ||||||
| 	// MIME content type of the static version of the emoji image. |  | ||||||
| 	ImageStaticContentType string `bun:",notnull"` |  | ||||||
| 	// Size of the emoji image file in bytes, for serving purposes. |  | ||||||
| 	ImageFileSize int `bun:",notnull"` |  | ||||||
| 	// Size of the static version of the emoji image file in bytes, for serving purposes. |  | ||||||
| 	ImageStaticFileSize int `bun:",notnull"` |  | ||||||
| 	// When was the emoji image last updated? |  | ||||||
| 	ImageUpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` |  | ||||||
| 	// Has a moderation action disabled this emoji from being shown? |  | ||||||
| 	Disabled bool `bun:",notnull,default:false"` |  | ||||||
| 	// ActivityStreams uri of this emoji. Something like 'https://example.org/emojis/1234' |  | ||||||
| 	URI string `bun:",notnull,unique"` |  | ||||||
| 	// Is this emoji visible in the admin emoji picker? |  | ||||||
| 	VisibleInPicker bool `bun:",notnull,default:true"` |  | ||||||
| 	// In which emoji category is this emoji visible? |  | ||||||
| 	CategoryID string `bun:"type:CHAR(26),nullzero"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										194
									
								
								internal/gtsmodel/emoji_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								internal/gtsmodel/emoji_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,194 @@ | ||||||
|  | /* | ||||||
|  |    GoToSocial | ||||||
|  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | ||||||
|  | 
 | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU Affero General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  |    You should have received a copy of the GNU Affero General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package gtsmodel_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func happyEmoji() *gtsmodel.Emoji { | ||||||
|  | 	// the file validator actually runs os.Stat on given paths, so we need to just create small | ||||||
|  | 	// temp files for both the main attachment file and the thumbnail | ||||||
|  | 
 | ||||||
|  | 	imageFile, err := os.CreateTemp("", "gts_test_emoji") | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	if _, err := imageFile.WriteString("main"); err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	imagePath := imageFile.Name() | ||||||
|  | 	if err := imageFile.Close(); err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	staticFile, err := os.CreateTemp("", "gts_test_emoji_static") | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	if _, err := staticFile.WriteString("thumbnail"); err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	imageStaticPath := staticFile.Name() | ||||||
|  | 	if err := staticFile.Close(); err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return >smodel.Emoji{ | ||||||
|  | 		ID:                     "01F8MH6NEM8D7527KZAECTCR76", | ||||||
|  | 		CreatedAt:              time.Now().Add(-71 * time.Hour), | ||||||
|  | 		UpdatedAt:              time.Now().Add(-71 * time.Hour), | ||||||
|  | 		Shortcode:              "blob_test", | ||||||
|  | 		Domain:                 "example.org", | ||||||
|  | 		ImageRemoteURL:         "https://example.org/emojis/blob_test.gif", | ||||||
|  | 		ImageStaticRemoteURL:   "https://example.org/emojis/blob_test.png", | ||||||
|  | 		ImageURL:               "", | ||||||
|  | 		ImageStaticURL:         "", | ||||||
|  | 		ImagePath:              imagePath, | ||||||
|  | 		ImageStaticPath:        imageStaticPath, | ||||||
|  | 		ImageContentType:       "image/gif", | ||||||
|  | 		ImageStaticContentType: "image/png", | ||||||
|  | 		ImageFileSize:          1024, | ||||||
|  | 		ImageStaticFileSize:    256, | ||||||
|  | 		ImageUpdatedAt:         time.Now(), | ||||||
|  | 		Disabled:               false, | ||||||
|  | 		URI:                    "https://example.org/emojis/blob_test", | ||||||
|  | 		VisibleInPicker:        true, | ||||||
|  | 		CategoryID:             "01FEE47ZH70PWDSEAVBRFNX325", | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type EmojiValidateTestSuite struct { | ||||||
|  | 	suite.Suite | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *EmojiValidateTestSuite) TestValidateEmojiHappyPath() { | ||||||
|  | 	// no problem here | ||||||
|  | 	m := happyEmoji() | ||||||
|  | 	err := gtsmodel.ValidateStruct(*m) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *EmojiValidateTestSuite) TestValidateEmojiBadFilePaths() { | ||||||
|  | 	e := happyEmoji() | ||||||
|  | 
 | ||||||
|  | 	e.ImagePath = "/tmp/nonexistent/file/for/gotosocial/test" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImagePath' Error:Field validation for 'ImagePath' failed on the 'file' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImagePath = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImagePath' Error:Field validation for 'ImagePath' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImagePath = "???????????thisnot a valid path####" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImagePath' Error:Field validation for 'ImagePath' failed on the 'file' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticPath = "/tmp/nonexistent/file/for/gotosocial/test" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImagePath' Error:Field validation for 'ImagePath' failed on the 'file' tag\nKey: 'Emoji.ImageStaticPath' Error:Field validation for 'ImageStaticPath' failed on the 'file' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticPath = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImagePath' Error:Field validation for 'ImagePath' failed on the 'file' tag\nKey: 'Emoji.ImageStaticPath' Error:Field validation for 'ImageStaticPath' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticPath = "???????????thisnot a valid path####" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImagePath' Error:Field validation for 'ImagePath' failed on the 'file' tag\nKey: 'Emoji.ImageStaticPath' Error:Field validation for 'ImageStaticPath' failed on the 'file' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *EmojiValidateTestSuite) TestValidateEmojiURI() { | ||||||
|  | 	e := happyEmoji() | ||||||
|  | 
 | ||||||
|  | 	e.URI = "aaaaaaaaaa" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.URI' Error:Field validation for 'URI' failed on the 'url' tag") | ||||||
|  | 
 | ||||||
|  | 	e.URI = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.URI' Error:Field validation for 'URI' failed on the 'url' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *EmojiValidateTestSuite) TestValidateEmojiURLCombos() { | ||||||
|  | 	e := happyEmoji() | ||||||
|  | 
 | ||||||
|  | 	e.ImageRemoteURL = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageRemoteURL' Error:Field validation for 'ImageRemoteURL' failed on the 'required_without' tag\nKey: 'Emoji.ImageURL' Error:Field validation for 'ImageURL' failed on the 'required_without' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageURL = "https://whatever.org" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticRemoteURL = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageStaticRemoteURL' Error:Field validation for 'ImageStaticRemoteURL' failed on the 'required_without' tag\nKey: 'Emoji.ImageStaticURL' Error:Field validation for 'ImageStaticURL' failed on the 'required_without' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticURL = "https://whatever.org" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	e.ImageURL = "" | ||||||
|  | 	e.ImageStaticURL = "" | ||||||
|  | 	e.ImageRemoteURL = "" | ||||||
|  | 	e.ImageStaticRemoteURL = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageRemoteURL' Error:Field validation for 'ImageRemoteURL' failed on the 'required_without' tag\nKey: 'Emoji.ImageStaticRemoteURL' Error:Field validation for 'ImageStaticRemoteURL' failed on the 'required_without' tag\nKey: 'Emoji.ImageURL' Error:Field validation for 'ImageURL' failed on the 'required_without' tag\nKey: 'Emoji.ImageStaticURL' Error:Field validation for 'ImageStaticURL' failed on the 'required_without' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *EmojiValidateTestSuite) TestValidateFileSize() { | ||||||
|  | 	e := happyEmoji() | ||||||
|  | 
 | ||||||
|  | 	e.ImageFileSize = 0 | ||||||
|  | 	err := gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageFileSize' Error:Field validation for 'ImageFileSize' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticFileSize = 0 | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageFileSize' Error:Field validation for 'ImageFileSize' failed on the 'required' tag\nKey: 'Emoji.ImageStaticFileSize' Error:Field validation for 'ImageStaticFileSize' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageFileSize = -1 | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageFileSize' Error:Field validation for 'ImageFileSize' failed on the 'min' tag\nKey: 'Emoji.ImageStaticFileSize' Error:Field validation for 'ImageStaticFileSize' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	e.ImageStaticFileSize = -1 | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageFileSize' Error:Field validation for 'ImageFileSize' failed on the 'min' tag\nKey: 'Emoji.ImageStaticFileSize' Error:Field validation for 'ImageStaticFileSize' failed on the 'min' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *EmojiValidateTestSuite) TestValidateDomain() { | ||||||
|  | 	e := happyEmoji() | ||||||
|  | 
 | ||||||
|  | 	e.Domain = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.ImageURL' Error:Field validation for 'ImageURL' failed on the 'required_without' tag\nKey: 'Emoji.ImageStaticURL' Error:Field validation for 'ImageStaticURL' failed on the 'required_without' tag") | ||||||
|  | 
 | ||||||
|  | 	e.Domain = "aaaaaaaaa" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*e) | ||||||
|  | 	suite.EqualError(err, "Key: 'Emoji.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestEmojiValidateTestSuite(t *testing.T) { | ||||||
|  | 	suite.Run(t, new(EmojiValidateTestSuite)) | ||||||
|  | } | ||||||
|  | @ -22,22 +22,14 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // Follow represents one account following another, and the metadata around that follow. | // Follow represents one account following another, and the metadata around that follow. | ||||||
| type Follow struct { | type Follow struct { | ||||||
| 	// id of this follow in the database | 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull,unique"` | 	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	// When was this follow created? | 	UpdatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	URI             string    `validate:"required,url" bun:",notnull,nullzero,unique"`                  // ActivityPub uri of this follow. | ||||||
| 	// When was this follow last updated? | 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),unique:srctarget,notnull"` // Who does this follow originate from? | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to accountID | ||||||
| 	// Who does this follow belong to? | 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),unique:srctarget,notnull"` // Who is the target of this follow ? | ||||||
| 	AccountID string   `bun:"type:CHAR(26),unique:srctarget,notnull"` | 	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to targetAccountID | ||||||
| 	Account   *Account `bun:"rel:belongs-to"` | 	ShowReblogs     bool      `validate:"-" bun:",nullzero,default:true"`                                // Does this follow also want to see reblogs and not just posts? | ||||||
| 	// Who does AccountID follow? | 	Notify          bool      `validate:"-" bun:",nullzero,default:false"`                              // does the following account want to be notified when the followed account posts? | ||||||
| 	TargetAccountID string   `bun:"type:CHAR(26),unique:srctarget,notnull"` |  | ||||||
| 	TargetAccount   *Account `bun:"rel:belongs-to"` |  | ||||||
| 	// Does this follow also want to see reblogs and not just posts? |  | ||||||
| 	ShowReblogs bool `bun:"default:true"` |  | ||||||
| 	// What is the activitypub URI of this follow? |  | ||||||
| 	URI string `bun:",unique,nullzero"` |  | ||||||
| 	// does the following account want to be notified when the followed account posts? |  | ||||||
| 	Notify bool |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										87
									
								
								internal/gtsmodel/follow_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								internal/gtsmodel/follow_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | ||||||
|  | /* | ||||||
|  |    GoToSocial | ||||||
|  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | ||||||
|  | 
 | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU Affero General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  |    You should have received a copy of the GNU Affero General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package gtsmodel_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func happyFollow() *gtsmodel.Follow { | ||||||
|  | 	return >smodel.Follow{ | ||||||
|  | 		ID:              "01FE91RJR88PSEEE30EV35QR8N", | ||||||
|  | 		CreatedAt:       time.Now(), | ||||||
|  | 		UpdatedAt:       time.Now(), | ||||||
|  | 		AccountID:       "01FE96MAE58MXCE5C4SSMEMCEK", | ||||||
|  | 		Account:         nil, | ||||||
|  | 		TargetAccountID: "01FE96MXRHWZHKC0WH5FT82H1A", | ||||||
|  | 		TargetAccount:   nil, | ||||||
|  | 		URI:             "https://example.org/users/user1/activity/follow/01FE91RJR88PSEEE30EV35QR8N", | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type FollowValidateTestSuite struct { | ||||||
|  | 	suite.Suite | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowValidateTestSuite) TestValidateFollowHappyPath() { | ||||||
|  | 	// no problem here | ||||||
|  | 	f := happyFollow() | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowValidateTestSuite) TestValidateFollowBadID() { | ||||||
|  | 	f := happyFollow() | ||||||
|  | 
 | ||||||
|  | 	f.ID = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'Follow.ID' Error:Field validation for 'ID' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	f.ID = "01FE96W293ZPRG9FQQP48HK8N001FE96W32AT24VYBGM12WN3GKB" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'Follow.ID' Error:Field validation for 'ID' failed on the 'ulid' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowValidateTestSuite) TestValidateFollowNoCreatedAt() { | ||||||
|  | 	f := happyFollow() | ||||||
|  | 
 | ||||||
|  | 	f.CreatedAt = time.Time{} | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowValidateTestSuite) TestValidateFollowNoURI() { | ||||||
|  | 	f := happyFollow() | ||||||
|  | 
 | ||||||
|  | 	f.URI = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'Follow.URI' Error:Field validation for 'URI' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	f.URI = "this-is-not-a-valid-url" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'Follow.URI' Error:Field validation for 'URI' failed on the 'url' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestFollowValidateTestSuite(t *testing.T) { | ||||||
|  | 	suite.Run(t, new(FollowValidateTestSuite)) | ||||||
|  | } | ||||||
|  | @ -22,22 +22,14 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // FollowRequest represents one account requesting to follow another, and the metadata around that request. | // FollowRequest represents one account requesting to follow another, and the metadata around that request. | ||||||
| type FollowRequest struct { | type FollowRequest struct { | ||||||
| 	// id of this follow request in the database | 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull,unique"` | 	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	// When was this follow request created? | 	UpdatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	URI             string    `validate:"required,url" bun:",notnull,nullzero,unique"`                  // ActivityPub uri of this follow (request). | ||||||
| 	// When was this follow request last updated? | 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull"` // Who does this follow request originate from? | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to accountID | ||||||
| 	// Who does this follow request originate from? | 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull"` // Who is the target of this follow request? | ||||||
| 	AccountID string   `bun:"type:CHAR(26),unique:frsrctarget,notnull"` | 	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // Account corresponding to targetAccountID | ||||||
| 	Account   *Account `bun:"rel:belongs-to"` | 	ShowReblogs     bool      `validate:"-" bun:",nullzero,default:true"`                                // Does this follow also want to see reblogs and not just posts? | ||||||
| 	// Who is the target of this follow request? | 	Notify          bool      `validate:"-" bun:",nullzero,default:false"`                              // does the following account want to be notified when the followed account posts? | ||||||
| 	TargetAccountID string   `bun:"type:CHAR(26),unique:frsrctarget,notnull"` |  | ||||||
| 	TargetAccount   *Account `bun:"rel:belongs-to"` |  | ||||||
| 	// Does this follow also want to see reblogs and not just posts? |  | ||||||
| 	ShowReblogs bool `bun:"default:true"` |  | ||||||
| 	// What is the activitypub URI of this follow request? |  | ||||||
| 	URI string `bun:",unique,nullzero"` |  | ||||||
| 	// does the following account want to be notified when the followed account posts? |  | ||||||
| 	Notify bool |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										87
									
								
								internal/gtsmodel/followrequest_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								internal/gtsmodel/followrequest_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | ||||||
|  | /* | ||||||
|  |    GoToSocial | ||||||
|  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | ||||||
|  | 
 | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU Affero General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  |    You should have received a copy of the GNU Affero General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package gtsmodel_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func happyFollowRequest() *gtsmodel.FollowRequest { | ||||||
|  | 	return >smodel.FollowRequest{ | ||||||
|  | 		ID:              "01FE91RJR88PSEEE30EV35QR8N", | ||||||
|  | 		CreatedAt:       time.Now(), | ||||||
|  | 		UpdatedAt:       time.Now(), | ||||||
|  | 		AccountID:       "01FE96MAE58MXCE5C4SSMEMCEK", | ||||||
|  | 		Account:         nil, | ||||||
|  | 		TargetAccountID: "01FE96MXRHWZHKC0WH5FT82H1A", | ||||||
|  | 		TargetAccount:   nil, | ||||||
|  | 		URI:             "https://example.org/users/user1/activity/follow/01FE91RJR88PSEEE30EV35QR8N", | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type FollowRequestValidateTestSuite struct { | ||||||
|  | 	suite.Suite | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowRequestValidateTestSuite) TestValidateFollowRequestHappyPath() { | ||||||
|  | 	// no problem here | ||||||
|  | 	f := happyFollowRequest() | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowRequestValidateTestSuite) TestValidateFollowRequestBadID() { | ||||||
|  | 	f := happyFollowRequest() | ||||||
|  | 
 | ||||||
|  | 	f.ID = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'FollowRequest.ID' Error:Field validation for 'ID' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	f.ID = "01FE96W293ZPRG9FQQP48HK8N001FE96W32AT24VYBGM12WN3GKB" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'FollowRequest.ID' Error:Field validation for 'ID' failed on the 'ulid' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowRequestValidateTestSuite) TestValidateFollowRequestNoCreatedAt() { | ||||||
|  | 	f := happyFollowRequest() | ||||||
|  | 
 | ||||||
|  | 	f.CreatedAt = time.Time{} | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *FollowRequestValidateTestSuite) TestValidateFollowRequestNoURI() { | ||||||
|  | 	f := happyFollowRequest() | ||||||
|  | 
 | ||||||
|  | 	f.URI = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'FollowRequest.URI' Error:Field validation for 'URI' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	f.URI = "this-is-not-a-valid-url" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*f) | ||||||
|  | 	suite.EqualError(err, "Key: 'FollowRequest.URI' Error:Field validation for 'URI' failed on the 'url' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestFollowRequestValidateTestSuite(t *testing.T) { | ||||||
|  | 	suite.Run(t, new(FollowRequestValidateTestSuite)) | ||||||
|  | } | ||||||
|  | @ -4,38 +4,22 @@ import "time" | ||||||
| 
 | 
 | ||||||
| // Instance represents a federated instance, either local or remote. | // Instance represents a federated instance, either local or remote. | ||||||
| type Instance struct { | type Instance struct { | ||||||
| 	// ID of this instance in the database | 	ID                     string       `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                     // id of this item in the database | ||||||
| 	ID string `bun:"type:CHAR(26),pk,notnull,unique"` | 	CreatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                              // when was item created | ||||||
| 	// Instance domain eg example.org | 	UpdatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                              // when was item last updated | ||||||
| 	Domain string `bun:",pk,notnull,unique"` | 	Domain                 string       `validate:"required,fqdn" bun:",nullzero,notnull,unique"`                                     // Instance domain eg example.org | ||||||
| 	// Title of this instance as it would like to be displayed. | 	Title                  string       `validate:"-" bun:",nullzero"`                                                                // Title of this instance as it would like to be displayed. | ||||||
| 	Title string `bun:",nullzero"` | 	URI                    string       `validate:"required,url" bun:",nullzero,notnull,unique"`                                      // base URI of this instance eg https://example.org | ||||||
| 	// base URI of this instance eg https://example.org | 	SuspendedAt            time.Time    `validate:"-" bun:",nullzero"`                                                                // When was this instance suspended, if at all? | ||||||
| 	URI string `bun:",notnull,unique"` | 	DomainBlockID          string       `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                      // ID of any existing domain block for this instance in the database | ||||||
| 	// When was this instance created in the db? | 	DomainBlock            *DomainBlock `validate:"-" bun:"rel:belongs-to"`                                                           // Domain block corresponding to domainBlockID | ||||||
| 	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	ShortDescription       string       `validate:"-" bun:",nullzero"`                                                                // Short description of this instance | ||||||
| 	// When was this instance last updated in the db? | 	Description            string       `validate:"-" bun:",nullzero"`                                                                // Longer description of this instance | ||||||
| 	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` | 	Terms                  string       `validate:"-" bun:",nullzero"`                                                                // Terms and conditions of this instance | ||||||
| 	// When was this instance suspended, if at all? | 	ContactEmail           string       `validate:"omitempty,email" bun:",nullzero"`                                                  // Contact email address for this instance | ||||||
| 	SuspendedAt time.Time `bun:",nullzero"` | 	ContactAccountUsername string       `validate:"required_with=ContactAccountID" bun:",nullzero"`                                   // Username of the contact account for this instance | ||||||
| 	// ID of any existing domain block for this instance in the database | 	ContactAccountID       string       `validate:"required_with=ContactAccountUsername,omitempty,ulid" bun:"type:CHAR(26),nullzero"` // Contact account ID in the database for this instance | ||||||
| 	DomainBlockID string       `bun:"type:CHAR(26),nullzero"` | 	ContactAccount         *Account     `validate:"-" bun:"rel:belongs-to"`                                                           // account corresponding to contactAccountID | ||||||
| 	DomainBlock   *DomainBlock `bun:"rel:belongs-to"` | 	Reputation             int64        `validate:"-" bun:",notnull,default:0"`                                                       // Reputation score of this instance | ||||||
| 	// Short description of this instance | 	Version                string       `validate:"-" bun:",nullzero"`                                                                // Version of the software used on this instance | ||||||
| 	ShortDescription string `bun:",nullzero"` |  | ||||||
| 	// Longer description of this instance |  | ||||||
| 	Description string `bun:",nullzero"` |  | ||||||
| 	// Terms and conditions of this instance |  | ||||||
| 	Terms string `bun:",nullzero"` |  | ||||||
| 	// Contact email address for this instance |  | ||||||
| 	ContactEmail string `bun:",nullzero"` |  | ||||||
| 	// Username of the contact account for this instance |  | ||||||
| 	ContactAccountUsername string `bun:",nullzero"` |  | ||||||
| 	// Contact account ID in the database for this instance |  | ||||||
| 	ContactAccountID string   `bun:"type:CHAR(26),nullzero"` |  | ||||||
| 	ContactAccount   *Account `bun:"rel:belongs-to"` |  | ||||||
| 	// Reputation score of this instance |  | ||||||
| 	Reputation int64 `bun:",notnull,default:0"` |  | ||||||
| 	// Version of the software used on this instance |  | ||||||
| 	Version string `bun:",nullzero"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										145
									
								
								internal/gtsmodel/instance_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								internal/gtsmodel/instance_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | ||||||
|  | /* | ||||||
|  |    GoToSocial | ||||||
|  |    Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org | ||||||
|  | 
 | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU Affero General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  |    You should have received a copy of the GNU Affero General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package gtsmodel_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func happyInstance() *gtsmodel.Instance { | ||||||
|  | 	return >smodel.Instance{ | ||||||
|  | 		ID:                     "01FE91RJR88PSEEE30EV35QR8N", | ||||||
|  | 		CreatedAt:              time.Now(), | ||||||
|  | 		UpdatedAt:              time.Now(), | ||||||
|  | 		Domain:                 "example.org", | ||||||
|  | 		Title:                  "Example Instance", | ||||||
|  | 		URI:                    "https://example.org", | ||||||
|  | 		SuspendedAt:            time.Time{}, | ||||||
|  | 		DomainBlockID:          "", | ||||||
|  | 		DomainBlock:            nil, | ||||||
|  | 		ShortDescription:       "This is a description for the example/testing instance.", | ||||||
|  | 		Description:            "This is a way longer description for the example/testing instance!", | ||||||
|  | 		Terms:                  "Don't be a knobhead.", | ||||||
|  | 		ContactEmail:           "admin@example.org", | ||||||
|  | 		ContactAccountUsername: "admin", | ||||||
|  | 		ContactAccountID:       "01FEE20H5QWHJDEXAEE9G96PR0", | ||||||
|  | 		ContactAccount:         nil, | ||||||
|  | 		Reputation:             420, | ||||||
|  | 		Version:                "gotosocial 0.1.0", | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type InstanceValidateTestSuite struct { | ||||||
|  | 	suite.Suite | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceHappyPath() { | ||||||
|  | 	// no problem here | ||||||
|  | 	m := happyInstance() | ||||||
|  | 	err := gtsmodel.ValidateStruct(*m) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceBadID() { | ||||||
|  | 	m := happyInstance() | ||||||
|  | 
 | ||||||
|  | 	m.ID = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*m) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.ID' Error:Field validation for 'ID' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	m.ID = "01FE96W293ZPRG9FQQP48HK8N001FE96W32AT24VYBGM12WN3GKB" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*m) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.ID' Error:Field validation for 'ID' failed on the 'ulid' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceAccountURI() { | ||||||
|  | 	i := happyInstance() | ||||||
|  | 
 | ||||||
|  | 	i.URI = "" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.URI' Error:Field validation for 'URI' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	i.URI = "---------------------------" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.URI' Error:Field validation for 'URI' failed on the 'url' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceDodgyAccountID() { | ||||||
|  | 	i := happyInstance() | ||||||
|  | 
 | ||||||
|  | 	i.ContactAccountID = "9HZJ76B6VXSKF" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.ContactAccountID' Error:Field validation for 'ContactAccountID' failed on the 'ulid' tag") | ||||||
|  | 
 | ||||||
|  | 	i.ContactAccountID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!!!!!!!!!!!" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.ContactAccountID' Error:Field validation for 'ContactAccountID' failed on the 'ulid' tag") | ||||||
|  | 
 | ||||||
|  | 	i.ContactAccountID = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.ContactAccountID' Error:Field validation for 'ContactAccountID' failed on the 'required_with' tag") | ||||||
|  | 
 | ||||||
|  | 	i.ContactAccountUsername = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceDomain() { | ||||||
|  | 	i := happyInstance() | ||||||
|  | 
 | ||||||
|  | 	i.Domain = "poopoo" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag") | ||||||
|  | 
 | ||||||
|  | 	i.Domain = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.Domain' Error:Field validation for 'Domain' failed on the 'required' tag") | ||||||
|  | 
 | ||||||
|  | 	i.Domain = "https://aaaaaaaaaaaaah.org" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceContactEmail() { | ||||||
|  | 	i := happyInstance() | ||||||
|  | 
 | ||||||
|  | 	i.ContactEmail = "poopoo" | ||||||
|  | 	err := gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.EqualError(err, "Key: 'Instance.ContactEmail' Error:Field validation for 'ContactEmail' failed on the 'email' tag") | ||||||
|  | 
 | ||||||
|  | 	i.ContactEmail = "" | ||||||
|  | 	err = gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *InstanceValidateTestSuite) TestValidateInstanceNoCreatedAt() { | ||||||
|  | 	i := happyInstance() | ||||||
|  | 
 | ||||||
|  | 	i.CreatedAt = time.Time{} | ||||||
|  | 	err := gtsmodel.ValidateStruct(*i) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestInstanceValidateTestSuite(t *testing.T) { | ||||||
|  | 	suite.Run(t, new(InstanceValidateTestSuite)) | ||||||
|  | } | ||||||
|  | @ -26,8 +26,8 @@ import ( | ||||||
| // somewhere in storage and that can be retrieved and served by the router. | // somewhere in storage and that can be retrieved and served by the router. | ||||||
| type MediaAttachment struct { | type MediaAttachment struct { | ||||||
| 	ID                string           `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                       // id of this item in the database | 	ID                string           `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                       // id of this item in the database | ||||||
| 	CreatedAt         time.Time        `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`                         // when was item created | 	CreatedAt         time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                // when was item created | ||||||
| 	UpdatedAt         time.Time        `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`                         // when was item last updated | 	UpdatedAt         time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                // when was item last updated | ||||||
| 	StatusID          string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                        // ID of the status to which this is attached | 	StatusID          string           `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                                        // ID of the status to which this is attached | ||||||
| 	URL               string           `validate:"required_without=RemoteURL,omitempty,url" bun:",nullzero"`                           // Where can the attachment be retrieved on *this* server | 	URL               string           `validate:"required_without=RemoteURL,omitempty,url" bun:",nullzero"`                           // Where can the attachment be retrieved on *this* server | ||||||
| 	RemoteURL         string           `validate:"required_without=URL,omitempty,url" bun:",nullzero"`                                 // Where can the attachment be retrieved on a remote server (empty for local media) | 	RemoteURL         string           `validate:"required_without=URL,omitempty,url" bun:",nullzero"`                                 // Where can the attachment be retrieved on a remote server (empty for local media) | ||||||
|  | @ -47,25 +47,26 @@ type MediaAttachment struct { | ||||||
| 
 | 
 | ||||||
| // File refers to the metadata for the whole file | // File refers to the metadata for the whole file | ||||||
| type File struct { | type File struct { | ||||||
| 	Path        string    `validate:"required,file" bun:",nullzero,notnull"`                      // Path of the file in storage. | 	Path        string    `validate:"required,file" bun:",nullzero,notnull"`               // Path of the file in storage. | ||||||
| 	ContentType string    `validate:"required" bun:",nullzero,notnull"`                           // MIME content type of the file. | 	ContentType string    `validate:"required" bun:",nullzero,notnull"`                    // MIME content type of the file. | ||||||
| 	FileSize    int       `validate:"required" bun:",nullzero,notnull"`                           // File size in bytes | 	FileSize    int       `validate:"required" bun:",nullzero,notnull"`                    // File size in bytes | ||||||
| 	UpdatedAt   time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"` // When was the file last updated. | 	UpdatedAt   time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"` // When was the file last updated. | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Thumbnail refers to a small image thumbnail derived from a larger image, video, or audio file. | // Thumbnail refers to a small image thumbnail derived from a larger image, video, or audio file. | ||||||
| type Thumbnail struct { | type Thumbnail struct { | ||||||
| 	Path        string    `validate:"required,file" bun:",nullzero,notnull"`                      // Path of the file in storage. | 	Path        string    `validate:"required,file" bun:",nullzero,notnull"`                    // Path of the file in storage. | ||||||
| 	ContentType string    `validate:"required" bun:",nullzero,notnull"`                           // MIME content type of the file. | 	ContentType string    `validate:"required" bun:",nullzero,notnull"`                         // MIME content type of the file. | ||||||
| 	FileSize    int       `validate:"required" bun:",nullzero,notnull"`                           // File size in bytes | 	FileSize    int       `validate:"required" bun:",nullzero,notnull"`                         // File size in bytes | ||||||
| 	UpdatedAt   time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"` // When was the file last updated. | 	UpdatedAt   time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`      // When was the file last updated. | ||||||
| 	URL         string    `validate:"required_without=RemoteURL,omitempty,url" bun:",nullzero"`   // What is the URL of the thumbnail on the local server | 	URL         string    `validate:"required_without=RemoteURL,omitempty,url" bun:",nullzero"` // What is the URL of the thumbnail on the local server | ||||||
| 	RemoteURL   string    `validate:"required_without=URL,omitempty,url" bun:",nullzero"`         // What is the remote URL of the thumbnail (empty for local media) | 	RemoteURL   string    `validate:"required_without=URL,omitempty,url" bun:",nullzero"`       // What is the remote URL of the thumbnail (empty for local media) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ProcessingStatus refers to how far along in the processing stage the attachment is. | // ProcessingStatus refers to how far along in the processing stage the attachment is. | ||||||
| type ProcessingStatus int | type ProcessingStatus int | ||||||
| 
 | 
 | ||||||
|  | // MediaAttachment processing states. | ||||||
| const ( | const ( | ||||||
| 	ProcessingStatusReceived   ProcessingStatus = 0   // ProcessingStatusReceived indicates the attachment has been received and is awaiting processing. No thumbnail available yet. | 	ProcessingStatusReceived   ProcessingStatus = 0   // ProcessingStatusReceived indicates the attachment has been received and is awaiting processing. No thumbnail available yet. | ||||||
| 	ProcessingStatusProcessing ProcessingStatus = 1   // ProcessingStatusProcessing indicates the attachment is currently being processed. Thumbnail is available but full media is not. | 	ProcessingStatusProcessing ProcessingStatus = 1   // ProcessingStatusProcessing indicates the attachment is currently being processed. Thumbnail is available but full media is not. | ||||||
|  | @ -76,6 +77,7 @@ const ( | ||||||
| // FileType refers to the file type of the media attaachment. | // FileType refers to the file type of the media attaachment. | ||||||
| type FileType string | type FileType string | ||||||
| 
 | 
 | ||||||
|  | // MediaAttachment file types. | ||||||
| const ( | const ( | ||||||
| 	FileTypeImage   FileType = "Image"   // FileTypeImage is for jpegs and pngs | 	FileTypeImage   FileType = "Image"   // FileTypeImage is for jpegs and pngs | ||||||
| 	FileTypeGif     FileType = "Gif"     // FileTypeGif is for native gifs and soundless videos that have been converted to gifs | 	FileTypeGif     FileType = "Gif"     // FileTypeGif is for native gifs and soundless videos that have been converted to gifs | ||||||
|  |  | ||||||
|  | @ -212,6 +212,18 @@ func (suite *MediaAttachmentValidateTestSuite) TestValidateMediaAttachmentBlurha | ||||||
| 	suite.NoError(err) | 	suite.NoError(err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *MediaAttachmentValidateTestSuite) TestValidateMediaAttachmentProcessing() { | ||||||
|  | 	m := happyMediaAttachment() | ||||||
|  | 
 | ||||||
|  | 	m.Processing = 420 | ||||||
|  | 	err := gtsmodel.ValidateStruct(*m) | ||||||
|  | 	suite.EqualError(err, "Key: 'MediaAttachment.Processing' Error:Field validation for 'Processing' failed on the 'oneof' tag") | ||||||
|  | 
 | ||||||
|  | 	m.Processing = -5 | ||||||
|  | 	err = gtsmodel.ValidateStruct(*m) | ||||||
|  | 	suite.EqualError(err, "Key: 'MediaAttachment.Processing' Error:Field validation for 'Processing' failed on the 'oneof' tag") | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestMediaAttachmentValidateTestSuite(t *testing.T) { | func TestMediaAttachmentValidateTestSuite(t *testing.T) { | ||||||
| 	suite.Run(t, new(MediaAttachmentValidateTestSuite)) | 	suite.Run(t, new(MediaAttachmentValidateTestSuite)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -23,8 +23,8 @@ import "time" | ||||||
| // Mention refers to the 'tagging' or 'mention' of a user within a status. | // Mention refers to the 'tagging' or 'mention' of a user within a status. | ||||||
| type Mention struct { | type Mention struct { | ||||||
| 	ID               string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | 	ID               string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	CreatedAt        time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created | 	CreatedAt        time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	UpdatedAt        time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item last updated | 	UpdatedAt        time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	StatusID         string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // ID of the status this mention originates from | 	StatusID         string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // ID of the status this mention originates from | ||||||
| 	Status           *Status   `validate:"-" bun:"rel:belongs-to"`                                       // status referred to by statusID | 	Status           *Status   `validate:"-" bun:"rel:belongs-to"`                                       // status referred to by statusID | ||||||
| 	OriginAccountID  string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // ID of the mention creator account | 	OriginAccountID  string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // ID of the mention creator account | ||||||
|  |  | ||||||
|  | @ -93,7 +93,7 @@ func (suite *MentionValidateTestSuite) TestValidateMentionNoCreatedAt() { | ||||||
| 
 | 
 | ||||||
| 	m.CreatedAt = time.Time{} | 	m.CreatedAt = time.Time{} | ||||||
| 	err := gtsmodel.ValidateStruct(*m) | 	err := gtsmodel.ValidateStruct(*m) | ||||||
| 	suite.EqualError(err, "Key: 'Mention.CreatedAt' Error:Field validation for 'CreatedAt' failed on the 'required' tag") | 	suite.NoError(err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestMentionValidateTestSuite(t *testing.T) { | func TestMentionValidateTestSuite(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ import "time" | ||||||
| // Notification models an alert/notification sent to an account about something like a reblog, like, new follow request, etc. | // Notification models an alert/notification sent to an account about something like a reblog, like, new follow request, etc. | ||||||
| type Notification struct { | type Notification struct { | ||||||
| 	ID               string           `validate:"ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                                                                                                                             // id of this item in the database | 	ID               string           `validate:"ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                                                                                                                                             // id of this item in the database | ||||||
| 	CreatedAt        time.Time        `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`                                                                                                                                      // when was item created | 	CreatedAt        time.Time        `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                                                                                                                             // when was item created | ||||||
| 	NotificationType NotificationType `validate:"oneof=follow follow_request mention reblog favourite poll status" bun:",nullzero,notnull"`                                                                                                        // Type of this notification | 	NotificationType NotificationType `validate:"oneof=follow follow_request mention reblog favourite poll status" bun:",nullzero,notnull"`                                                                                                        // Type of this notification | ||||||
| 	TargetAccountID  string           `validate:"ulid" bun:"type:CHAR(26),nullzero,notnull"`                                                                                                                                                       // Which account does this notification target (ie., who will receive the notification?) | 	TargetAccountID  string           `validate:"ulid" bun:"type:CHAR(26),nullzero,notnull"`                                                                                                                                                       // Which account does this notification target (ie., who will receive the notification?) | ||||||
| 	TargetAccount    *Account         `validate:"-" bun:"rel:belongs-to"`                                                                                                                                                                          // Which account performed the action that created this notification? | 	TargetAccount    *Account         `validate:"-" bun:"rel:belongs-to"`                                                                                                                                                                          // Which account performed the action that created this notification? | ||||||
|  | @ -37,6 +37,7 @@ type Notification struct { | ||||||
| // NotificationType describes the reason/type of this notification. | // NotificationType describes the reason/type of this notification. | ||||||
| type NotificationType string | type NotificationType string | ||||||
| 
 | 
 | ||||||
|  | // Notification Types | ||||||
| const ( | const ( | ||||||
| 	NotificationFollow        NotificationType = "follow"         // NotificationFollow -- someone followed you | 	NotificationFollow        NotificationType = "follow"         // NotificationFollow -- someone followed you | ||||||
| 	NotificationFollowRequest NotificationType = "follow_request" // NotificationFollowRequest -- someone requested to follow you | 	NotificationFollowRequest NotificationType = "follow_request" // NotificationFollowRequest -- someone requested to follow you | ||||||
|  |  | ||||||
|  | @ -89,7 +89,7 @@ func (suite *NotificationValidateTestSuite) TestValidateNotificationNoCreatedAt( | ||||||
| 
 | 
 | ||||||
| 	m.CreatedAt = time.Time{} | 	m.CreatedAt = time.Time{} | ||||||
| 	err := gtsmodel.ValidateStruct(*m) | 	err := gtsmodel.ValidateStruct(*m) | ||||||
| 	suite.EqualError(err, "Key: 'Notification.CreatedAt' Error:Field validation for 'CreatedAt' failed on the 'required' tag") | 	suite.NoError(err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestNotificationValidateTestSuite(t *testing.T) { | func TestNotificationValidateTestSuite(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -20,30 +20,17 @@ package gtsmodel | ||||||
| 
 | 
 | ||||||
| // Relationship describes a requester's relationship with another account. | // Relationship describes a requester's relationship with another account. | ||||||
| type Relationship struct { | type Relationship struct { | ||||||
| 	// The account id. | 	ID                  string // The account id. | ||||||
| 	ID string | 	Following           bool   // Are you following this user? | ||||||
| 	// Are you following this user? | 	ShowingReblogs      bool   // Are you receiving this user's boosts in your home timeline? | ||||||
| 	Following bool | 	Notifying           bool   // Have you enabled notifications for this user? | ||||||
| 	// Are you receiving this user's boosts in your home timeline? | 	FollowedBy          bool   // Are you followed by this user? | ||||||
| 	ShowingReblogs bool | 	Blocking            bool   // Are you blocking this user? | ||||||
| 	// Have you enabled notifications for this user? | 	BlockedBy           bool   // Is this user blocking you? | ||||||
| 	Notifying bool | 	Muting              bool   // Are you muting this user? | ||||||
| 	// Are you followed by this user? | 	MutingNotifications bool   // Are you muting notifications from this user? | ||||||
| 	FollowedBy bool | 	Requested           bool   // Do you have a pending follow request for this user? | ||||||
| 	// Are you blocking this user? | 	DomainBlocking      bool   // Are you blocking this user's domain? | ||||||
| 	Blocking bool | 	Endorsed            bool   // Are you featuring this user on your profile? | ||||||
| 	// Is this user blocking you? | 	Note                string // Your note on this account. | ||||||
| 	BlockedBy bool |  | ||||||
| 	// Are you muting this user? |  | ||||||
| 	Muting bool |  | ||||||
| 	// Are you muting notifications from this user? |  | ||||||
| 	MutingNotifications bool |  | ||||||
| 	// Do you have a pending follow request for this user? |  | ||||||
| 	Requested bool |  | ||||||
| 	// Are you blocking this user's domain? |  | ||||||
| 	DomainBlocking bool |  | ||||||
| 	// Are you featuring this user on your profile? |  | ||||||
| 	Endorsed bool |  | ||||||
| 	// Your note on this account. |  | ||||||
| 	Note string |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -25,8 +25,8 @@ import ( | ||||||
| // Status represents a user-created 'post' or 'status' in the database, either remote or local | // Status represents a user-created 'post' or 'status' in the database, either remote or local | ||||||
| type Status struct { | type Status struct { | ||||||
| 	ID                       string             `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                              // id of this item in the database | 	ID                       string             `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"`                              // id of this item in the database | ||||||
| 	CreatedAt                time.Time          `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`                                // when was item created | 	CreatedAt                time.Time          `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                       // when was item created | ||||||
| 	UpdatedAt                time.Time          `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`                                // when was item last updated | 	UpdatedAt                time.Time          `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`                                       // when was item last updated | ||||||
| 	URI                      string             `validate:"required,url" bun:",unique,nullzero,notnull"`                                               // activitypub URI of this status | 	URI                      string             `validate:"required,url" bun:",unique,nullzero,notnull"`                                               // activitypub URI of this status | ||||||
| 	URL                      string             `validate:"url" bun:",nullzero"`                                                                       // web url for viewing this status | 	URL                      string             `validate:"url" bun:",nullzero"`                                                                       // web url for viewing this status | ||||||
| 	Content                  string             `validate:"-" bun:",nullzero"`                                                                         // content of this status; likely html-formatted but not guaranteed | 	Content                  string             `validate:"-" bun:",nullzero"`                                                                         // content of this status; likely html-formatted but not guaranteed | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -67,7 +68,7 @@ func happyStatus() *gtsmodel.Status { | ||||||
| 			Replyable: true, | 			Replyable: true, | ||||||
| 			Likeable:  true, | 			Likeable:  true, | ||||||
| 		}, | 		}, | ||||||
| 		ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 		ActivityStreamsType: ap.ObjectNote, | ||||||
| 		Text:                "Test status! #hello", | 		Text:                "Test status! #hello", | ||||||
| 		Pinned:              false, | 		Pinned:              false, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ import "time" | ||||||
| // StatusBookmark refers to one account having a 'bookmark' of the status of another account. | // StatusBookmark refers to one account having a 'bookmark' of the status of another account. | ||||||
| type StatusBookmark struct { | type StatusBookmark struct { | ||||||
| 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	CreatedAt       time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created | 	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the bookmark | 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the bookmark | ||||||
| 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account that created the bookmark | 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account that created the bookmark | ||||||
| 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the bookmarked status | 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the bookmarked status | ||||||
|  |  | ||||||
|  | @ -79,7 +79,7 @@ func (suite *StatusBookmarkValidateTestSuite) TestValidateStatusBookmarkNoCreate | ||||||
| 
 | 
 | ||||||
| 	m.CreatedAt = time.Time{} | 	m.CreatedAt = time.Time{} | ||||||
| 	err := gtsmodel.ValidateStruct(*m) | 	err := gtsmodel.ValidateStruct(*m) | ||||||
| 	suite.EqualError(err, "Key: 'StatusBookmark.CreatedAt' Error:Field validation for 'CreatedAt' failed on the 'required' tag") | 	suite.NoError(err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestStatusBookmarkValidateTestSuite(t *testing.T) { | func TestStatusBookmarkValidateTestSuite(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ import "time" | ||||||
| // StatusFave refers to a 'fave' or 'like' in the database, from one account, targeting the status of another account | // StatusFave refers to a 'fave' or 'like' in the database, from one account, targeting the status of another account | ||||||
| type StatusFave struct { | type StatusFave struct { | ||||||
| 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	CreatedAt       time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created | 	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the fave | 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the fave | ||||||
| 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account that created the fave | 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // account that created the fave | ||||||
| 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the faved status | 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the faved status | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ func (suite *StatusFaveValidateTestSuite) TestValidateStatusFaveNoCreatedAt() { | ||||||
| 
 | 
 | ||||||
| 	f.CreatedAt = time.Time{} | 	f.CreatedAt = time.Time{} | ||||||
| 	err := gtsmodel.ValidateStruct(*f) | 	err := gtsmodel.ValidateStruct(*f) | ||||||
| 	suite.EqualError(err, "Key: 'StatusFave.CreatedAt' Error:Field validation for 'CreatedAt' failed on the 'required' tag") | 	suite.NoError(err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *StatusFaveValidateTestSuite) TestValidateStatusFaveNoURI() { | func (suite *StatusFaveValidateTestSuite) TestValidateStatusFaveNoURI() { | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ import "time" | ||||||
| // StatusMute refers to one account having muted the status of another account or its own. | // StatusMute refers to one account having muted the status of another account or its own. | ||||||
| type StatusMute struct { | type StatusMute struct { | ||||||
| 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | 	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	CreatedAt       time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created | 	CreatedAt       time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the mute | 	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the mute | ||||||
| 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the account specified by accountID | 	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the account specified by accountID | ||||||
| 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the muted status (can be the same as accountID) | 	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the muted status (can be the same as accountID) | ||||||
|  |  | ||||||
|  | @ -79,7 +79,7 @@ func (suite *StatusMuteValidateTestSuite) TestValidateStatusMuteNoCreatedAt() { | ||||||
| 
 | 
 | ||||||
| 	m.CreatedAt = time.Time{} | 	m.CreatedAt = time.Time{} | ||||||
| 	err := gtsmodel.ValidateStruct(*m) | 	err := gtsmodel.ValidateStruct(*m) | ||||||
| 	suite.EqualError(err, "Key: 'StatusMute.CreatedAt' Error:Field validation for 'CreatedAt' failed on the 'required' tag") | 	suite.NoError(err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestStatusMuteValidateTestSuite(t *testing.T) { | func TestStatusMuteValidateTestSuite(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -23,12 +23,12 @@ import "time" | ||||||
| // Tag represents a hashtag for gathering public statuses together. | // Tag represents a hashtag for gathering public statuses together. | ||||||
| type Tag struct { | type Tag struct { | ||||||
| 	ID                     string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | 	ID                     string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	CreatedAt              time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created | 	CreatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	UpdatedAt              time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item last updated | 	UpdatedAt              time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	URL                    string    `validate:"required,url" bun:",nullzero,notnull"`                         // Href of this tag, eg https://example.org/tags/somehashtag | 	URL                    string    `validate:"required,url" bun:",nullzero,notnull"`                         // Href/web address of this tag, eg https://example.org/tags/somehashtag | ||||||
| 	Name                   string    `validate:"required" bun:",unique,nullzero,notnull"`                      // name of this tag -- the tag without the hash part | 	Name                   string    `validate:"required" bun:",unique,nullzero,notnull"`                      // name of this tag -- the tag without the hash part | ||||||
| 	FirstSeenFromAccountID string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                  // Which account ID is the first one we saw using this tag? | 	FirstSeenFromAccountID string    `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"`                  // Which account ID is the first one we saw using this tag? | ||||||
| 	Useable                bool      `validate:"-" bun:",notnull,default:true"`                                // can our instance users use this tag? | 	Useable                bool      `validate:"-" bun:",notnull,default:true"`                                // can our instance users use this tag? | ||||||
| 	Listable               bool      `validate:"-" bun:",notnull,default:true"`                                // can our instance users look up this tag? | 	Listable               bool      `validate:"-" bun:",notnull,default:true"`                                // can our instance users look up this tag? | ||||||
| 	LastStatusAt           time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was this tag last used? | 	LastStatusAt           time.Time `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was this tag last used? | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,8 +27,8 @@ import ( | ||||||
| // To cross reference this local user with their account (which can be local or remote), use the AccountID field. | // To cross reference this local user with their account (which can be local or remote), use the AccountID field. | ||||||
| type User struct { | type User struct { | ||||||
| 	ID                     string       `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | 	ID                     string       `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database | ||||||
| 	CreatedAt              time.Time    `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created | 	CreatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item created | ||||||
| 	UpdatedAt              time.Time    `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item last updated | 	UpdatedAt              time.Time    `validate:"-" bun:",nullzero,notnull,default:current_timestamp"`          // when was item last updated | ||||||
| 	Email                  string       `validate:"required_with=ConfirmedAt" bun:",nullzero,unique"`             // confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported | 	Email                  string       `validate:"required_with=ConfirmedAt" bun:",nullzero,unique"`             // confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported | ||||||
| 	AccountID              string       `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull,unique"`    // The id of the local gtsmodel.Account entry for this user. | 	AccountID              string       `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull,unique"`    // The id of the local gtsmodel.Account entry for this user. | ||||||
| 	Account                *Account     `validate:"-" bun:"rel:belongs-to"`                                       // Pointer to the account of this user that corresponds to AccountID. | 	Account                *Account     `validate:"-" bun:"rel:belongs-to"`                                       // Pointer to the account of this user that corresponds to AccountID. | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| var v *validator.Validate | var v *validator.Validate | ||||||
| 
 | 
 | ||||||
|  | // Validation Panic messages | ||||||
| const ( | const ( | ||||||
| 	PointerValidationPanic = "validate function was passed pointer" | 	PointerValidationPanic = "validate function was passed pointer" | ||||||
| 	InvalidValidationPanic = "validate function was passed invalid item" | 	InvalidValidationPanic = "validate function was passed invalid item" | ||||||
|  | @ -48,6 +49,7 @@ func init() { | ||||||
| 	v.RegisterValidation("ulid", ulidValidator) | 	v.RegisterValidation("ulid", ulidValidator) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // ValidateStruct validates the passed struct, returning validator.ValidationErrors if invalid, or nil if OK. | ||||||
| func ValidateStruct(s interface{}) error { | func ValidateStruct(s interface{}) error { | ||||||
| 	switch reflect.ValueOf(s).Kind() { | 	switch reflect.ValueOf(s).Kind() { | ||||||
| 	case reflect.Invalid: | 	case reflect.Invalid: | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| const randomRange = 631152381 // ~20 years in seconds | const randomRange = 631152381 // ~20 years in seconds | ||||||
| 
 | 
 | ||||||
|  | // ULID represents a Universally Unique Lexicographically Sortable Identifier of 26 characters. See https://github.com/oklog/ulid | ||||||
| type ULID string | type ULID string | ||||||
| 
 | 
 | ||||||
| // NewULID returns a new ULID string using the current time, or an error if something goes wrong. | // NewULID returns a new ULID string using the current time, or an error if something goes wrong. | ||||||
|  |  | ||||||
|  | @ -16,21 +16,23 @@ | ||||||
|    along with this program.  If not, see <http://www.gnu.org/licenses/>. |    along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| package gtsmodel | package messages | ||||||
| 
 | 
 | ||||||
| // FromClientAPI wraps a message that travels from client API into the processor | import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 
 | ||||||
|  | // FromClientAPI wraps a message that travels from the client API into the processor. | ||||||
| type FromClientAPI struct { | type FromClientAPI struct { | ||||||
| 	APObjectType   string | 	APObjectType   string | ||||||
| 	APActivityType string | 	APActivityType string | ||||||
| 	GTSModel       interface{} | 	GTSModel       interface{} | ||||||
| 	OriginAccount  *Account | 	OriginAccount  *gtsmodel.Account | ||||||
| 	TargetAccount  *Account | 	TargetAccount  *gtsmodel.Account | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FromFederator wraps a message that travels from the federator into the processor | // FromFederator wraps a message that travels from the federator into the processor. | ||||||
| type FromFederator struct { | type FromFederator struct { | ||||||
| 	APObjectType     string | 	APObjectType     string | ||||||
| 	APActivityType   string | 	APActivityType   string | ||||||
| 	GTSModel         interface{} | 	GTSModel         interface{} | ||||||
| 	ReceivingAccount *Account | 	ReceivingAccount *gtsmodel.Account | ||||||
| } | } | ||||||
|  | @ -30,6 +30,7 @@ import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/media" | 	"github.com/superseriousbusiness/gotosocial/internal/media" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/visibility" | 	"github.com/superseriousbusiness/gotosocial/internal/visibility" | ||||||
|  | @ -79,7 +80,7 @@ type processor struct { | ||||||
| 	tc            typeutils.TypeConverter | 	tc            typeutils.TypeConverter | ||||||
| 	config        *config.Config | 	config        *config.Config | ||||||
| 	mediaHandler  media.Handler | 	mediaHandler  media.Handler | ||||||
| 	fromClientAPI chan gtsmodel.FromClientAPI | 	fromClientAPI chan messages.FromClientAPI | ||||||
| 	oauthServer   oauth.Server | 	oauthServer   oauth.Server | ||||||
| 	filter        visibility.Filter | 	filter        visibility.Filter | ||||||
| 	db            db.DB | 	db            db.DB | ||||||
|  | @ -88,7 +89,7 @@ type processor struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New returns a new account processor. | // New returns a new account processor. | ||||||
| func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, oauthServer oauth.Server, fromClientAPI chan gtsmodel.FromClientAPI, federator federation.Federator, config *config.Config, log *logrus.Logger) Processor { | func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, oauthServer oauth.Server, fromClientAPI chan messages.FromClientAPI, federator federation.Federator, config *config.Config, log *logrus.Logger) Processor { | ||||||
| 	return &processor{ | 	return &processor{ | ||||||
| 		tc:            tc, | 		tc:            tc, | ||||||
| 		config:        config, | 		config:        config, | ||||||
|  |  | ||||||
|  | @ -22,11 +22,13 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -111,9 +113,9 @@ func (p *processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel | ||||||
| 
 | 
 | ||||||
| 	// follow request status changed so send the UNDO activity to the channel for async processing | 	// follow request status changed so send the UNDO activity to the channel for async processing | ||||||
| 	if frChanged { | 	if frChanged { | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsFollow, | 			APObjectType:   ap.ActivityFollow, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel: >smodel.Follow{ | 			GTSModel: >smodel.Follow{ | ||||||
| 				AccountID:       requestingAccount.ID, | 				AccountID:       requestingAccount.ID, | ||||||
| 				TargetAccountID: targetAccountID, | 				TargetAccountID: targetAccountID, | ||||||
|  | @ -126,9 +128,9 @@ func (p *processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel | ||||||
| 
 | 
 | ||||||
| 	// follow status changed so send the UNDO activity to the channel for async processing | 	// follow status changed so send the UNDO activity to the channel for async processing | ||||||
| 	if fChanged { | 	if fChanged { | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsFollow, | 			APObjectType:   ap.ActivityFollow, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel: >smodel.Follow{ | 			GTSModel: >smodel.Follow{ | ||||||
| 				AccountID:       requestingAccount.ID, | 				AccountID:       requestingAccount.ID, | ||||||
| 				TargetAccountID: targetAccountID, | 				TargetAccountID: targetAccountID, | ||||||
|  | @ -140,9 +142,9 @@ func (p *processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// handle the rest of the block process asynchronously | 	// handle the rest of the block process asynchronously | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsBlock, | 		APObjectType:   ap.ActivityBlock, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsCreate, | 		APActivityType: ap.ActivityCreate, | ||||||
| 		GTSModel:       block, | 		GTSModel:       block, | ||||||
| 		OriginAccount:  requestingAccount, | 		OriginAccount:  requestingAccount, | ||||||
| 		TargetAccount:  targetAccount, | 		TargetAccount:  targetAccount, | ||||||
|  |  | ||||||
|  | @ -22,11 +22,13 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -99,9 +101,9 @@ func (p *processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// otherwise we leave the follow request as it is and we handle the rest of the process asynchronously | 	// otherwise we leave the follow request as it is and we handle the rest of the process asynchronously | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsFollow, | 		APObjectType:   ap.ActivityFollow, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsCreate, | 		APActivityType: ap.ActivityCreate, | ||||||
| 		GTSModel:       fr, | 		GTSModel:       fr, | ||||||
| 		OriginAccount:  requestingAccount, | 		OriginAccount:  requestingAccount, | ||||||
| 		TargetAccount:  targetAcct, | 		TargetAccount:  targetAcct, | ||||||
|  |  | ||||||
|  | @ -23,8 +23,10 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -150,9 +152,9 @@ selectStatusesLoop: | ||||||
| 			// pass the status delete through the client api channel for processing | 			// pass the status delete through the client api channel for processing | ||||||
| 			s.Account = account | 			s.Account = account | ||||||
| 			l.Debug("putting status in the client api channel") | 			l.Debug("putting status in the client api channel") | ||||||
| 			p.fromClientAPI <- gtsmodel.FromClientAPI{ | 			p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 				APObjectType:   gtsmodel.ActivityStreamsNote, | 				APObjectType:   ap.ObjectNote, | ||||||
| 				APActivityType: gtsmodel.ActivityStreamsDelete, | 				APActivityType: ap.ActivityDelete, | ||||||
| 				GTSModel:       s, | 				GTSModel:       s, | ||||||
| 				OriginAccount:  account, | 				OriginAccount:  account, | ||||||
| 				TargetAccount:  account, | 				TargetAccount:  account, | ||||||
|  | @ -186,9 +188,9 @@ selectStatusesLoop: | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				l.Debug("putting boost undo in the client api channel") | 				l.Debug("putting boost undo in the client api channel") | ||||||
| 				p.fromClientAPI <- gtsmodel.FromClientAPI{ | 				p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 					APObjectType:   gtsmodel.ActivityStreamsAnnounce, | 					APObjectType:   ap.ActivityAnnounce, | ||||||
| 					APActivityType: gtsmodel.ActivityStreamsUndo, | 					APActivityType: ap.ActivityUndo, | ||||||
| 					GTSModel:       s, | 					GTSModel:       s, | ||||||
| 					OriginAccount:  b.Account, | 					OriginAccount:  b.Account, | ||||||
| 					TargetAccount:  account, | 					TargetAccount:  account, | ||||||
|  |  | ||||||
|  | @ -22,10 +22,12 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) BlockRemove(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) { | func (p *processor) BlockRemove(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) { | ||||||
|  | @ -52,9 +54,9 @@ func (p *processor) BlockRemove(ctx context.Context, requestingAccount *gtsmodel | ||||||
| 
 | 
 | ||||||
| 	// block status changed so send the UNDO activity to the channel for async processing | 	// block status changed so send the UNDO activity to the channel for async processing | ||||||
| 	if blockChanged { | 	if blockChanged { | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsBlock, | 			APObjectType:   ap.ActivityBlock, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel:       block, | 			GTSModel:       block, | ||||||
| 			OriginAccount:  requestingAccount, | 			OriginAccount:  requestingAccount, | ||||||
| 			TargetAccount:  targetAccount, | 			TargetAccount:  targetAccount, | ||||||
|  |  | ||||||
|  | @ -22,10 +22,12 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) FollowRemove(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) { | func (p *processor) FollowRemove(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) { | ||||||
|  | @ -78,9 +80,9 @@ func (p *processor) FollowRemove(ctx context.Context, requestingAccount *gtsmode | ||||||
| 
 | 
 | ||||||
| 	// follow request status changed so send the UNDO activity to the channel for async processing | 	// follow request status changed so send the UNDO activity to the channel for async processing | ||||||
| 	if frChanged { | 	if frChanged { | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsFollow, | 			APObjectType:   ap.ActivityFollow, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel: >smodel.Follow{ | 			GTSModel: >smodel.Follow{ | ||||||
| 				AccountID:       requestingAccount.ID, | 				AccountID:       requestingAccount.ID, | ||||||
| 				TargetAccountID: targetAccountID, | 				TargetAccountID: targetAccountID, | ||||||
|  | @ -93,9 +95,9 @@ func (p *processor) FollowRemove(ctx context.Context, requestingAccount *gtsmode | ||||||
| 
 | 
 | ||||||
| 	// follow status changed so send the UNDO activity to the channel for async processing | 	// follow status changed so send the UNDO activity to the channel for async processing | ||||||
| 	if fChanged { | 	if fChanged { | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsFollow, | 			APObjectType:   ap.ActivityFollow, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel: >smodel.Follow{ | 			GTSModel: >smodel.Follow{ | ||||||
| 				AccountID:       requestingAccount.ID, | 				AccountID:       requestingAccount.ID, | ||||||
| 				TargetAccountID: targetAccountID, | 				TargetAccountID: targetAccountID, | ||||||
|  |  | ||||||
|  | @ -26,9 +26,11 @@ import ( | ||||||
| 	"io" | 	"io" | ||||||
| 	"mime/multipart" | 	"mime/multipart" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/media" | 	"github.com/superseriousbusiness/gotosocial/internal/media" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/text" | 	"github.com/superseriousbusiness/gotosocial/internal/text" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
|  | @ -122,9 +124,9 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form | ||||||
| 		return nil, fmt.Errorf("could not fetch updated account %s: %s", account.ID, err) | 		return nil, fmt.Errorf("could not fetch updated account %s: %s", account.ID, err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsProfile, | 		APObjectType:   ap.ObjectProfile, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsUpdate, | 		APActivityType: ap.ActivityUpdate, | ||||||
| 		GTSModel:       updatedAccount, | 		GTSModel:       updatedAccount, | ||||||
| 		OriginAccount:  updatedAccount, | 		OriginAccount:  updatedAccount, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/media" | 	"github.com/superseriousbusiness/gotosocial/internal/media" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -46,13 +47,13 @@ type processor struct { | ||||||
| 	tc            typeutils.TypeConverter | 	tc            typeutils.TypeConverter | ||||||
| 	config        *config.Config | 	config        *config.Config | ||||||
| 	mediaHandler  media.Handler | 	mediaHandler  media.Handler | ||||||
| 	fromClientAPI chan gtsmodel.FromClientAPI | 	fromClientAPI chan messages.FromClientAPI | ||||||
| 	db            db.DB | 	db            db.DB | ||||||
| 	log           *logrus.Logger | 	log           *logrus.Logger | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New returns a new admin processor. | // New returns a new admin processor. | ||||||
| func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, fromClientAPI chan gtsmodel.FromClientAPI, config *config.Config, log *logrus.Logger) Processor { | func New(db db.DB, tc typeutils.TypeConverter, mediaHandler media.Handler, fromClientAPI chan messages.FromClientAPI, config *config.Config, log *logrus.Logger) Processor { | ||||||
| 	return &processor{ | 	return &processor{ | ||||||
| 		tc:            tc, | 		tc:            tc, | ||||||
| 		config:        config, | 		config:        config, | ||||||
|  |  | ||||||
|  | @ -24,11 +24,13 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/text" | 	"github.com/superseriousbusiness/gotosocial/internal/text" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -140,9 +142,9 @@ selectAccountsLoop: | ||||||
| 			l.Debugf("putting delete for account %s in the clientAPI channel", a.Username) | 			l.Debugf("putting delete for account %s in the clientAPI channel", a.Username) | ||||||
| 
 | 
 | ||||||
| 			// pass the account delete through the client api channel for processing | 			// pass the account delete through the client api channel for processing | ||||||
| 			p.fromClientAPI <- gtsmodel.FromClientAPI{ | 			p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 				APObjectType:   gtsmodel.ActivityStreamsPerson, | 				APObjectType:   ap.ActorPerson, | ||||||
| 				APActivityType: gtsmodel.ActivityStreamsDelete, | 				APActivityType: ap.ActivityDelete, | ||||||
| 				GTSModel:       block, | 				GTSModel:       block, | ||||||
| 				OriginAccount:  account, | 				OriginAccount:  account, | ||||||
| 				TargetAccount:  a, | 				TargetAccount:  a, | ||||||
|  |  | ||||||
|  | @ -21,10 +21,11 @@ package processing | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -77,9 +78,9 @@ func (p *processor) FollowRequestAccept(ctx context.Context, auth *oauth.Auth, a | ||||||
| 		follow.TargetAccount = followTargetAccount | 		follow.TargetAccount = followTargetAccount | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsFollow, | 		APObjectType:   ap.ActivityFollow, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsAccept, | 		APActivityType: ap.ActivityAccept, | ||||||
| 		GTSModel:       follow, | 		GTSModel:       follow, | ||||||
| 		OriginAccount:  follow.Account, | 		OriginAccount:  follow.Account, | ||||||
| 		TargetAccount:  follow.TargetAccount, | 		TargetAccount:  follow.TargetAccount, | ||||||
|  |  | ||||||
|  | @ -25,16 +25,18 @@ import ( | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 
 | 
 | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel.FromClientAPI) error { | func (p *processor) processFromClientAPI(ctx context.Context, clientMsg messages.FromClientAPI) error { | ||||||
| 	switch clientMsg.APActivityType { | 	switch clientMsg.APActivityType { | ||||||
| 	case gtsmodel.ActivityStreamsCreate: | 	case ap.ActivityCreate: | ||||||
| 		// CREATE | 		// CREATE | ||||||
| 		switch clientMsg.APObjectType { | 		switch clientMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsNote: | 		case ap.ObjectNote: | ||||||
| 			// CREATE NOTE | 			// CREATE NOTE | ||||||
| 			status, ok := clientMsg.GTSModel.(*gtsmodel.Status) | 			status, ok := clientMsg.GTSModel.(*gtsmodel.Status) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -52,7 +54,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 			if status.VisibilityAdvanced.Federated { | 			if status.VisibilityAdvanced.Federated { | ||||||
| 				return p.federateStatus(ctx, status) | 				return p.federateStatus(ctx, status) | ||||||
| 			} | 			} | ||||||
| 		case gtsmodel.ActivityStreamsFollow: | 		case ap.ActivityFollow: | ||||||
| 			// CREATE FOLLOW REQUEST | 			// CREATE FOLLOW REQUEST | ||||||
| 			followRequest, ok := clientMsg.GTSModel.(*gtsmodel.FollowRequest) | 			followRequest, ok := clientMsg.GTSModel.(*gtsmodel.FollowRequest) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -64,7 +66,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return p.federateFollow(ctx, followRequest, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateFollow(ctx, followRequest, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		case gtsmodel.ActivityStreamsLike: | 		case ap.ActivityLike: | ||||||
| 			// CREATE LIKE/FAVE | 			// CREATE LIKE/FAVE | ||||||
| 			fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave) | 			fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -76,7 +78,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return p.federateFave(ctx, fave, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateFave(ctx, fave, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		case gtsmodel.ActivityStreamsAnnounce: | 		case ap.ActivityAnnounce: | ||||||
| 			// CREATE BOOST/ANNOUNCE | 			// CREATE BOOST/ANNOUNCE | ||||||
| 			boostWrapperStatus, ok := clientMsg.GTSModel.(*gtsmodel.Status) | 			boostWrapperStatus, ok := clientMsg.GTSModel.(*gtsmodel.Status) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -92,7 +94,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return p.federateAnnounce(ctx, boostWrapperStatus, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateAnnounce(ctx, boostWrapperStatus, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		case gtsmodel.ActivityStreamsBlock: | 		case ap.ActivityBlock: | ||||||
| 			// CREATE BLOCK | 			// CREATE BLOCK | ||||||
| 			block, ok := clientMsg.GTSModel.(*gtsmodel.Block) | 			block, ok := clientMsg.GTSModel.(*gtsmodel.Block) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -112,10 +114,10 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 
 | 
 | ||||||
| 			return p.federateBlock(ctx, block) | 			return p.federateBlock(ctx, block) | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsUpdate: | 	case ap.ActivityUpdate: | ||||||
| 		// UPDATE | 		// UPDATE | ||||||
| 		switch clientMsg.APObjectType { | 		switch clientMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsProfile, gtsmodel.ActivityStreamsPerson: | 		case ap.ObjectProfile, ap.ActorPerson: | ||||||
| 			// UPDATE ACCOUNT/PROFILE | 			// UPDATE ACCOUNT/PROFILE | ||||||
| 			account, ok := clientMsg.GTSModel.(*gtsmodel.Account) | 			account, ok := clientMsg.GTSModel.(*gtsmodel.Account) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -124,10 +126,10 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 
 | 
 | ||||||
| 			return p.federateAccountUpdate(ctx, account, clientMsg.OriginAccount) | 			return p.federateAccountUpdate(ctx, account, clientMsg.OriginAccount) | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsAccept: | 	case ap.ActivityAccept: | ||||||
| 		// ACCEPT | 		// ACCEPT | ||||||
| 		switch clientMsg.APObjectType { | 		switch clientMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsFollow: | 		case ap.ActivityFollow: | ||||||
| 			// ACCEPT FOLLOW | 			// ACCEPT FOLLOW | ||||||
| 			follow, ok := clientMsg.GTSModel.(*gtsmodel.Follow) | 			follow, ok := clientMsg.GTSModel.(*gtsmodel.Follow) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -140,31 +142,31 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 
 | 
 | ||||||
| 			return p.federateAcceptFollowRequest(ctx, follow, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateAcceptFollowRequest(ctx, follow, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsUndo: | 	case ap.ActivityUndo: | ||||||
| 		// UNDO | 		// UNDO | ||||||
| 		switch clientMsg.APObjectType { | 		switch clientMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsFollow: | 		case ap.ActivityFollow: | ||||||
| 			// UNDO FOLLOW | 			// UNDO FOLLOW | ||||||
| 			follow, ok := clientMsg.GTSModel.(*gtsmodel.Follow) | 			follow, ok := clientMsg.GTSModel.(*gtsmodel.Follow) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("undo was not parseable as *gtsmodel.Follow") | 				return errors.New("undo was not parseable as *gtsmodel.Follow") | ||||||
| 			} | 			} | ||||||
| 			return p.federateUnfollow(ctx, follow, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateUnfollow(ctx, follow, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		case gtsmodel.ActivityStreamsBlock: | 		case ap.ActivityBlock: | ||||||
| 			// UNDO BLOCK | 			// UNDO BLOCK | ||||||
| 			block, ok := clientMsg.GTSModel.(*gtsmodel.Block) | 			block, ok := clientMsg.GTSModel.(*gtsmodel.Block) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("undo was not parseable as *gtsmodel.Block") | 				return errors.New("undo was not parseable as *gtsmodel.Block") | ||||||
| 			} | 			} | ||||||
| 			return p.federateUnblock(ctx, block) | 			return p.federateUnblock(ctx, block) | ||||||
| 		case gtsmodel.ActivityStreamsLike: | 		case ap.ActivityLike: | ||||||
| 			// UNDO LIKE/FAVE | 			// UNDO LIKE/FAVE | ||||||
| 			fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave) | 			fave, ok := clientMsg.GTSModel.(*gtsmodel.StatusFave) | ||||||
| 			if !ok { | 			if !ok { | ||||||
| 				return errors.New("undo was not parseable as *gtsmodel.StatusFave") | 				return errors.New("undo was not parseable as *gtsmodel.StatusFave") | ||||||
| 			} | 			} | ||||||
| 			return p.federateUnfave(ctx, fave, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateUnfave(ctx, fave, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		case gtsmodel.ActivityStreamsAnnounce: | 		case ap.ActivityAnnounce: | ||||||
| 			// UNDO ANNOUNCE/BOOST | 			// UNDO ANNOUNCE/BOOST | ||||||
| 			boost, ok := clientMsg.GTSModel.(*gtsmodel.Status) | 			boost, ok := clientMsg.GTSModel.(*gtsmodel.Status) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -177,10 +179,10 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 
 | 
 | ||||||
| 			return p.federateUnannounce(ctx, boost, clientMsg.OriginAccount, clientMsg.TargetAccount) | 			return p.federateUnannounce(ctx, boost, clientMsg.OriginAccount, clientMsg.TargetAccount) | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsDelete: | 	case ap.ActivityDelete: | ||||||
| 		// DELETE | 		// DELETE | ||||||
| 		switch clientMsg.APObjectType { | 		switch clientMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsNote: | 		case ap.ObjectNote: | ||||||
| 			// DELETE STATUS/NOTE | 			// DELETE STATUS/NOTE | ||||||
| 			statusToDelete, ok := clientMsg.GTSModel.(*gtsmodel.Status) | 			statusToDelete, ok := clientMsg.GTSModel.(*gtsmodel.Status) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -216,7 +218,7 @@ func (p *processor) processFromClientAPI(ctx context.Context, clientMsg gtsmodel | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return p.federateStatusDelete(ctx, statusToDelete) | 			return p.federateStatusDelete(ctx, statusToDelete) | ||||||
| 		case gtsmodel.ActivityStreamsProfile, gtsmodel.ActivityStreamsPerson: | 		case ap.ObjectProfile, ap.ActorPerson: | ||||||
| 			// DELETE ACCOUNT/PROFILE | 			// DELETE ACCOUNT/PROFILE | ||||||
| 
 | 
 | ||||||
| 			// the origin of the delete could be either a domain block, or an action by another (or this) account | 			// the origin of the delete could be either a domain block, or an action by another (or this) account | ||||||
|  |  | ||||||
|  | @ -25,12 +25,14 @@ import ( | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmodel.FromFederator) error { | func (p *processor) processFromFederator(ctx context.Context, federatorMsg messages.FromFederator) error { | ||||||
| 	l := p.log.WithFields(logrus.Fields{ | 	l := p.log.WithFields(logrus.Fields{ | ||||||
| 		"func":         "processFromFederator", | 		"func":         "processFromFederator", | ||||||
| 		"federatorMsg": fmt.Sprintf("%+v", federatorMsg), | 		"federatorMsg": fmt.Sprintf("%+v", federatorMsg), | ||||||
|  | @ -39,10 +41,10 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 	l.Trace("entering function PROCESS FROM FEDERATOR") | 	l.Trace("entering function PROCESS FROM FEDERATOR") | ||||||
| 
 | 
 | ||||||
| 	switch federatorMsg.APActivityType { | 	switch federatorMsg.APActivityType { | ||||||
| 	case gtsmodel.ActivityStreamsCreate: | 	case ap.ActivityCreate: | ||||||
| 		// CREATE | 		// CREATE | ||||||
| 		switch federatorMsg.APObjectType { | 		switch federatorMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsNote: | 		case ap.ObjectNote: | ||||||
| 			// CREATE A STATUS | 			// CREATE A STATUS | ||||||
| 			incomingStatus, ok := federatorMsg.GTSModel.(*gtsmodel.Status) | 			incomingStatus, ok := federatorMsg.GTSModel.(*gtsmodel.Status) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -61,10 +63,10 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 			if err := p.notifyStatus(ctx, status); err != nil { | 			if err := p.notifyStatus(ctx, status); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 		case gtsmodel.ActivityStreamsProfile: | 		case ap.ObjectProfile: | ||||||
| 			// CREATE AN ACCOUNT | 			// CREATE AN ACCOUNT | ||||||
| 			// nothing to do here | 			// nothing to do here | ||||||
| 		case gtsmodel.ActivityStreamsLike: | 		case ap.ActivityLike: | ||||||
| 			// CREATE A FAVE | 			// CREATE A FAVE | ||||||
| 			incomingFave, ok := federatorMsg.GTSModel.(*gtsmodel.StatusFave) | 			incomingFave, ok := federatorMsg.GTSModel.(*gtsmodel.StatusFave) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -74,7 +76,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 			if err := p.notifyFave(ctx, incomingFave, federatorMsg.ReceivingAccount); err != nil { | 			if err := p.notifyFave(ctx, incomingFave, federatorMsg.ReceivingAccount); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 		case gtsmodel.ActivityStreamsFollow: | 		case ap.ActivityFollow: | ||||||
| 			// CREATE A FOLLOW REQUEST | 			// CREATE A FOLLOW REQUEST | ||||||
| 			incomingFollowRequest, ok := federatorMsg.GTSModel.(*gtsmodel.FollowRequest) | 			incomingFollowRequest, ok := federatorMsg.GTSModel.(*gtsmodel.FollowRequest) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -84,7 +86,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 			if err := p.notifyFollowRequest(ctx, incomingFollowRequest, federatorMsg.ReceivingAccount); err != nil { | 			if err := p.notifyFollowRequest(ctx, incomingFollowRequest, federatorMsg.ReceivingAccount); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 		case gtsmodel.ActivityStreamsAnnounce: | 		case ap.ActivityAnnounce: | ||||||
| 			// CREATE AN ANNOUNCE | 			// CREATE AN ANNOUNCE | ||||||
| 			incomingAnnounce, ok := federatorMsg.GTSModel.(*gtsmodel.Status) | 			incomingAnnounce, ok := federatorMsg.GTSModel.(*gtsmodel.Status) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -114,7 +116,7 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 			if err := p.notifyAnnounce(ctx, incomingAnnounce); err != nil { | 			if err := p.notifyAnnounce(ctx, incomingAnnounce); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 		case gtsmodel.ActivityStreamsBlock: | 		case ap.ActivityBlock: | ||||||
| 			// CREATE A BLOCK | 			// CREATE A BLOCK | ||||||
| 			block, ok := federatorMsg.GTSModel.(*gtsmodel.Block) | 			block, ok := federatorMsg.GTSModel.(*gtsmodel.Block) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -131,10 +133,10 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 			// TODO: same with notifications | 			// TODO: same with notifications | ||||||
| 			// TODO: same with bookmarks | 			// TODO: same with bookmarks | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsUpdate: | 	case ap.ActivityUpdate: | ||||||
| 		// UPDATE | 		// UPDATE | ||||||
| 		switch federatorMsg.APObjectType { | 		switch federatorMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsProfile: | 		case ap.ObjectProfile: | ||||||
| 			// UPDATE AN ACCOUNT | 			// UPDATE AN ACCOUNT | ||||||
| 			incomingAccount, ok := federatorMsg.GTSModel.(*gtsmodel.Account) | 			incomingAccount, ok := federatorMsg.GTSModel.(*gtsmodel.Account) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  | @ -150,10 +152,10 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 				return fmt.Errorf("error dereferencing account from federator: %s", err) | 				return fmt.Errorf("error dereferencing account from federator: %s", err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsDelete: | 	case ap.ActivityDelete: | ||||||
| 		// DELETE | 		// DELETE | ||||||
| 		switch federatorMsg.APObjectType { | 		switch federatorMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsNote: | 		case ap.ObjectNote: | ||||||
| 			// DELETE A STATUS | 			// DELETE A STATUS | ||||||
| 			// TODO: handle side effects of status deletion here: | 			// TODO: handle side effects of status deletion here: | ||||||
| 			// 1. delete all media associated with status | 			// 1. delete all media associated with status | ||||||
|  | @ -185,14 +187,14 @@ func (p *processor) processFromFederator(ctx context.Context, federatorMsg gtsmo | ||||||
| 
 | 
 | ||||||
| 			// remove this status from any and all timelines | 			// remove this status from any and all timelines | ||||||
| 			return p.deleteStatusFromTimelines(ctx, statusToDelete) | 			return p.deleteStatusFromTimelines(ctx, statusToDelete) | ||||||
| 		case gtsmodel.ActivityStreamsProfile: | 		case ap.ObjectProfile: | ||||||
| 			// DELETE A PROFILE/ACCOUNT | 			// DELETE A PROFILE/ACCOUNT | ||||||
| 			// TODO: handle side effects of account deletion here: delete all objects, statuses, media etc associated with account | 			// TODO: handle side effects of account deletion here: delete all objects, statuses, media etc associated with account | ||||||
| 		} | 		} | ||||||
| 	case gtsmodel.ActivityStreamsAccept: | 	case ap.ActivityAccept: | ||||||
| 		// ACCEPT | 		// ACCEPT | ||||||
| 		switch federatorMsg.APObjectType { | 		switch federatorMsg.APObjectType { | ||||||
| 		case gtsmodel.ActivityStreamsFollow: | 		case ap.ActivityFollow: | ||||||
| 			// ACCEPT A FOLLOW | 			// ACCEPT A FOLLOW | ||||||
| 			follow, ok := federatorMsg.GTSModel.(*gtsmodel.Follow) | 			follow, ok := federatorMsg.GTSModel.(*gtsmodel.Follow) | ||||||
| 			if !ok { | 			if !ok { | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/media" | 	"github.com/superseriousbusiness/gotosocial/internal/media" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/processing/account" | 	"github.com/superseriousbusiness/gotosocial/internal/processing/account" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/processing/admin" | 	"github.com/superseriousbusiness/gotosocial/internal/processing/admin" | ||||||
|  | @ -219,8 +220,8 @@ type Processor interface { | ||||||
| 
 | 
 | ||||||
| // processor just implements the Processor interface | // processor just implements the Processor interface | ||||||
| type processor struct { | type processor struct { | ||||||
| 	fromClientAPI   chan gtsmodel.FromClientAPI | 	fromClientAPI   chan messages.FromClientAPI | ||||||
| 	fromFederator   chan gtsmodel.FromFederator | 	fromFederator   chan messages.FromFederator | ||||||
| 	federator       federation.Federator | 	federator       federation.Federator | ||||||
| 	stop            chan interface{} | 	stop            chan interface{} | ||||||
| 	log             *logrus.Logger | 	log             *logrus.Logger | ||||||
|  | @ -247,8 +248,8 @@ type processor struct { | ||||||
| // NewProcessor returns a new Processor that uses the given federator and logger | // NewProcessor returns a new Processor that uses the given federator and logger | ||||||
| func NewProcessor(config *config.Config, tc typeutils.TypeConverter, federator federation.Federator, oauthServer oauth.Server, mediaHandler media.Handler, storage blob.Storage, timelineManager timeline.Manager, db db.DB, log *logrus.Logger) Processor { | func NewProcessor(config *config.Config, tc typeutils.TypeConverter, federator federation.Federator, oauthServer oauth.Server, mediaHandler media.Handler, storage blob.Storage, timelineManager timeline.Manager, db db.DB, log *logrus.Logger) Processor { | ||||||
| 
 | 
 | ||||||
| 	fromClientAPI := make(chan gtsmodel.FromClientAPI, 1000) | 	fromClientAPI := make(chan messages.FromClientAPI, 1000) | ||||||
| 	fromFederator := make(chan gtsmodel.FromFederator, 1000) | 	fromFederator := make(chan messages.FromFederator, 1000) | ||||||
| 
 | 
 | ||||||
| 	statusProcessor := status.New(db, tc, config, fromClientAPI, log) | 	statusProcessor := status.New(db, tc, config, fromClientAPI, log) | ||||||
| 	streamingProcessor := streaming.New(db, tc, oauthServer, config, log) | 	streamingProcessor := streaming.New(db, tc, oauthServer, config, log) | ||||||
|  |  | ||||||
|  | @ -23,9 +23,11 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) Boost(ctx context.Context, requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | func (p *processor) Boost(ctx context.Context, requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | ||||||
|  | @ -63,9 +65,9 @@ func (p *processor) Boost(ctx context.Context, requestingAccount *gtsmodel.Accou | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// send it back to the processor for async processing | 	// send it back to the processor for async processing | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsAnnounce, | 		APObjectType:   ap.ActivityAnnounce, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsCreate, | 		APActivityType: ap.ActivityCreate, | ||||||
| 		GTSModel:       boostWrapperStatus, | 		GTSModel:       boostWrapperStatus, | ||||||
| 		OriginAccount:  requestingAccount, | 		OriginAccount:  requestingAccount, | ||||||
| 		TargetAccount:  targetStatus.Account, | 		TargetAccount:  targetStatus.Account, | ||||||
|  |  | ||||||
|  | @ -23,10 +23,12 @@ import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/text" | 	"github.com/superseriousbusiness/gotosocial/internal/text" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
|  | @ -50,7 +52,7 @@ func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, appli | ||||||
| 		AccountID:                account.ID, | 		AccountID:                account.ID, | ||||||
| 		AccountURI:               account.URI, | 		AccountURI:               account.URI, | ||||||
| 		ContentWarning:           text.RemoveHTML(form.SpoilerText), | 		ContentWarning:           text.RemoveHTML(form.SpoilerText), | ||||||
| 		ActivityStreamsType:      gtsmodel.ActivityStreamsNote, | 		ActivityStreamsType:      ap.ObjectNote, | ||||||
| 		Sensitive:                form.Sensitive, | 		Sensitive:                form.Sensitive, | ||||||
| 		Language:                 form.Language, | 		Language:                 form.Language, | ||||||
| 		CreatedWithApplicationID: application.ID, | 		CreatedWithApplicationID: application.ID, | ||||||
|  | @ -95,9 +97,9 @@ func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, appli | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// send it back to the processor for async processing | 	// send it back to the processor for async processing | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsNote, | 		APObjectType:   ap.ObjectNote, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsCreate, | 		APActivityType: ap.ActivityCreate, | ||||||
| 		GTSModel:       newStatus, | 		GTSModel:       newStatus, | ||||||
| 		OriginAccount:  account, | 		OriginAccount:  account, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -23,9 +23,11 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | 	"github.com/superseriousbusiness/gotosocial/internal/gtserror" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) Delete(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | func (p *processor) Delete(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | ||||||
|  | @ -51,9 +53,9 @@ func (p *processor) Delete(ctx context.Context, requestingAccount *gtsmodel.Acco | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// send it back to the processor for async processing | 	// send it back to the processor for async processing | ||||||
| 	p.fromClientAPI <- gtsmodel.FromClientAPI{ | 	p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 		APObjectType:   gtsmodel.ActivityStreamsNote, | 		APObjectType:   ap.ObjectNote, | ||||||
| 		APActivityType: gtsmodel.ActivityStreamsDelete, | 		APActivityType: ap.ActivityDelete, | ||||||
| 		GTSModel:       targetStatus, | 		GTSModel:       targetStatus, | ||||||
| 		OriginAccount:  requestingAccount, | 		OriginAccount:  requestingAccount, | ||||||
| 		TargetAccount:  requestingAccount, | 		TargetAccount:  requestingAccount, | ||||||
|  |  | ||||||
|  | @ -23,11 +23,13 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/id" | 	"github.com/superseriousbusiness/gotosocial/internal/id" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -82,9 +84,9 @@ func (p *processor) Fave(ctx context.Context, requestingAccount *gtsmodel.Accoun | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// send it back to the processor for async processing | 		// send it back to the processor for async processing | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsLike, | 			APObjectType:   ap.ActivityLike, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsCreate, | 			APActivityType: ap.ActivityCreate, | ||||||
| 			GTSModel:       gtsFave, | 			GTSModel:       gtsFave, | ||||||
| 			OriginAccount:  requestingAccount, | 			OriginAccount:  requestingAccount, | ||||||
| 			TargetAccount:  targetStatus.Account, | 			TargetAccount:  targetStatus.Account, | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"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" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/text" | 	"github.com/superseriousbusiness/gotosocial/internal/text" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/visibility" | 	"github.com/superseriousbusiness/gotosocial/internal/visibility" | ||||||
|  | @ -75,12 +76,12 @@ type processor struct { | ||||||
| 	db            db.DB | 	db            db.DB | ||||||
| 	filter        visibility.Filter | 	filter        visibility.Filter | ||||||
| 	formatter     text.Formatter | 	formatter     text.Formatter | ||||||
| 	fromClientAPI chan gtsmodel.FromClientAPI | 	fromClientAPI chan messages.FromClientAPI | ||||||
| 	log           *logrus.Logger | 	log           *logrus.Logger | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New returns a new status processor. | // New returns a new status processor. | ||||||
| func New(db db.DB, tc typeutils.TypeConverter, config *config.Config, fromClientAPI chan gtsmodel.FromClientAPI, log *logrus.Logger) Processor { | func New(db db.DB, tc typeutils.TypeConverter, config *config.Config, fromClientAPI chan messages.FromClientAPI, log *logrus.Logger) Processor { | ||||||
| 	return &processor{ | 	return &processor{ | ||||||
| 		tc:            tc, | 		tc:            tc, | ||||||
| 		config:        config, | 		config:        config, | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/config" | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/processing/status" | 	"github.com/superseriousbusiness/gotosocial/internal/processing/status" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | 	"github.com/superseriousbusiness/gotosocial/internal/typeutils" | ||||||
|  | @ -36,7 +37,7 @@ type StatusStandardTestSuite struct { | ||||||
| 	db                db.DB | 	db                db.DB | ||||||
| 	log               *logrus.Logger | 	log               *logrus.Logger | ||||||
| 	typeConverter     typeutils.TypeConverter | 	typeConverter     typeutils.TypeConverter | ||||||
| 	fromClientAPIChan chan gtsmodel.FromClientAPI | 	fromClientAPIChan chan messages.FromClientAPI | ||||||
| 
 | 
 | ||||||
| 	// standard suite models | 	// standard suite models | ||||||
| 	testTokens       map[string]*oauth.Token | 	testTokens       map[string]*oauth.Token | ||||||
|  |  | ||||||
|  | @ -23,10 +23,12 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) Unboost(ctx context.Context, requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | func (p *processor) Unboost(ctx context.Context, requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | ||||||
|  | @ -89,9 +91,9 @@ func (p *processor) Unboost(ctx context.Context, requestingAccount *gtsmodel.Acc | ||||||
| 		gtsBoost.BoostOf.Account = targetStatus.Account | 		gtsBoost.BoostOf.Account = targetStatus.Account | ||||||
| 
 | 
 | ||||||
| 		// send it back to the processor for async processing | 		// send it back to the processor for async processing | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsAnnounce, | 			APObjectType:   ap.ActivityAnnounce, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel:       gtsBoost, | 			GTSModel:       gtsBoost, | ||||||
| 			OriginAccount:  requestingAccount, | 			OriginAccount:  requestingAccount, | ||||||
| 			TargetAccount:  targetStatus.Account, | 			TargetAccount:  targetStatus.Account, | ||||||
|  |  | ||||||
|  | @ -23,10 +23,12 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	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/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" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *processor) Unfave(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | func (p *processor) Unfave(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { | ||||||
|  | @ -71,9 +73,9 @@ func (p *processor) Unfave(ctx context.Context, requestingAccount *gtsmodel.Acco | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// send it back to the processor for async processing | 		// send it back to the processor for async processing | ||||||
| 		p.fromClientAPI <- gtsmodel.FromClientAPI{ | 		p.fromClientAPI <- messages.FromClientAPI{ | ||||||
| 			APObjectType:   gtsmodel.ActivityStreamsLike, | 			APObjectType:   ap.ActivityLike, | ||||||
| 			APActivityType: gtsmodel.ActivityStreamsUndo, | 			APActivityType: ap.ActivityUndo, | ||||||
| 			GTSModel:       gtsFave, | 			GTSModel:       gtsFave, | ||||||
| 			OriginAccount:  requestingAccount, | 			OriginAccount:  requestingAccount, | ||||||
| 			TargetAccount:  targetStatus.Account, | 			TargetAccount:  targetStatus.Account, | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ( | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/api/model" | 	"github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/messages" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/processing/status" | 	"github.com/superseriousbusiness/gotosocial/internal/processing/status" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/testrig" | 	"github.com/superseriousbusiness/gotosocial/testrig" | ||||||
| ) | ) | ||||||
|  | @ -68,7 +69,7 @@ func (suite *UtilTestSuite) SetupTest() { | ||||||
| 	suite.db = testrig.NewTestDB() | 	suite.db = testrig.NewTestDB() | ||||||
| 	suite.log = testrig.NewTestLog() | 	suite.log = testrig.NewTestLog() | ||||||
| 	suite.typeConverter = testrig.NewTestTypeConverter(suite.db) | 	suite.typeConverter = testrig.NewTestTypeConverter(suite.db) | ||||||
| 	suite.fromClientAPIChan = make(chan gtsmodel.FromClientAPI, 100) | 	suite.fromClientAPIChan = make(chan messages.FromClientAPI, 100) | ||||||
| 	suite.status = status.New(suite.db, suite.typeConverter, suite.config, suite.fromClientAPIChan, suite.log) | 	suite.status = status.New(suite.db, suite.typeConverter, suite.config, suite.fromClientAPIChan, suite.log) | ||||||
| 
 | 
 | ||||||
| 	testrig.StandardDBSetup(suite.db, nil) | 	testrig.StandardDBSetup(suite.db, nil) | ||||||
|  |  | ||||||
|  | @ -94,15 +94,15 @@ func (c *converter) ASRepresentationToAccount(ctx context.Context, accountable a | ||||||
| 
 | 
 | ||||||
| 	// check for bot and actor type | 	// check for bot and actor type | ||||||
| 	switch accountable.GetTypeName() { | 	switch accountable.GetTypeName() { | ||||||
| 	case gtsmodel.ActivityStreamsPerson, gtsmodel.ActivityStreamsGroup, gtsmodel.ActivityStreamsOrganization: | 	case ap.ActorPerson, ap.ActorGroup, ap.ActorOrganization: | ||||||
| 		// people, groups, and organizations aren't bots | 		// people, groups, and organizations aren't bots | ||||||
| 		acct.Bot = false | 		acct.Bot = false | ||||||
| 		// apps and services are | 		// apps and services are | ||||||
| 	case gtsmodel.ActivityStreamsApplication, gtsmodel.ActivityStreamsService: | 	case ap.ActorApplication, ap.ActorService: | ||||||
| 		acct.Bot = true | 		acct.Bot = true | ||||||
| 	default: | 	default: | ||||||
| 		// we don't know what this is! | 		// we don't know what this is! | ||||||
| 		return nil, fmt.Errorf("type name %s not recognised or not convertible to gtsmodel.ActivityStreamsActor", accountable.GetTypeName()) | 		return nil, fmt.Errorf("type name %s not recognised or not convertible to ap.ActivityStreamsActor", accountable.GetTypeName()) | ||||||
| 	} | 	} | ||||||
| 	acct.ActorType = accountable.GetTypeName() | 	acct.ActorType = accountable.GetTypeName() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ import ( | ||||||
| 	"github.com/go-fed/activity/pub" | 	"github.com/go-fed/activity/pub" | ||||||
| 	"github.com/go-fed/activity/streams" | 	"github.com/go-fed/activity/streams" | ||||||
| 	"github.com/go-fed/activity/streams/vocab" | 	"github.com/go-fed/activity/streams/vocab" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | 	"github.com/superseriousbusiness/gotosocial/internal/oauth" | ||||||
| ) | ) | ||||||
|  | @ -291,7 +292,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account { | ||||||
| 			FollowersURI:            "http://localhost:8080/users/weed_lord420/followers", | 			FollowersURI:            "http://localhost:8080/users/weed_lord420/followers", | ||||||
| 			FollowingURI:            "http://localhost:8080/users/weed_lord420/following", | 			FollowingURI:            "http://localhost:8080/users/weed_lord420/following", | ||||||
| 			FeaturedCollectionURI:   "http://localhost:8080/users/weed_lord420/collections/featured", | 			FeaturedCollectionURI:   "http://localhost:8080/users/weed_lord420/collections/featured", | ||||||
| 			ActorType:               gtsmodel.ActivityStreamsPerson, | 			ActorType:               ap.ActorPerson, | ||||||
| 			AlsoKnownAs:             "", | 			AlsoKnownAs:             "", | ||||||
| 			PrivateKey:              &rsa.PrivateKey{}, | 			PrivateKey:              &rsa.PrivateKey{}, | ||||||
| 			PublicKey:               &rsa.PublicKey{}, | 			PublicKey:               &rsa.PublicKey{}, | ||||||
|  | @ -330,7 +331,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account { | ||||||
| 			FollowersURI:            "http://localhost:8080/users/admin/followers", | 			FollowersURI:            "http://localhost:8080/users/admin/followers", | ||||||
| 			FollowingURI:            "http://localhost:8080/users/admin/following", | 			FollowingURI:            "http://localhost:8080/users/admin/following", | ||||||
| 			FeaturedCollectionURI:   "http://localhost:8080/users/admin/collections/featured", | 			FeaturedCollectionURI:   "http://localhost:8080/users/admin/collections/featured", | ||||||
| 			ActorType:               gtsmodel.ActivityStreamsPerson, | 			ActorType:               ap.ActorPerson, | ||||||
| 			AlsoKnownAs:             "", | 			AlsoKnownAs:             "", | ||||||
| 			PrivateKey:              &rsa.PrivateKey{}, | 			PrivateKey:              &rsa.PrivateKey{}, | ||||||
| 			PublicKey:               &rsa.PublicKey{}, | 			PublicKey:               &rsa.PublicKey{}, | ||||||
|  | @ -367,7 +368,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account { | ||||||
| 			FollowersURI:            "http://localhost:8080/users/the_mighty_zork/followers", | 			FollowersURI:            "http://localhost:8080/users/the_mighty_zork/followers", | ||||||
| 			FollowingURI:            "http://localhost:8080/users/the_mighty_zork/following", | 			FollowingURI:            "http://localhost:8080/users/the_mighty_zork/following", | ||||||
| 			FeaturedCollectionURI:   "http://localhost:8080/users/the_mighty_zork/collections/featured", | 			FeaturedCollectionURI:   "http://localhost:8080/users/the_mighty_zork/collections/featured", | ||||||
| 			ActorType:               gtsmodel.ActivityStreamsPerson, | 			ActorType:               ap.ActorPerson, | ||||||
| 			AlsoKnownAs:             "", | 			AlsoKnownAs:             "", | ||||||
| 			PrivateKey:              &rsa.PrivateKey{}, | 			PrivateKey:              &rsa.PrivateKey{}, | ||||||
| 			PublicKey:               &rsa.PublicKey{}, | 			PublicKey:               &rsa.PublicKey{}, | ||||||
|  | @ -405,7 +406,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account { | ||||||
| 			FollowersURI:            "http://localhost:8080/users/1happyturtle/followers", | 			FollowersURI:            "http://localhost:8080/users/1happyturtle/followers", | ||||||
| 			FollowingURI:            "http://localhost:8080/users/1happyturtle/following", | 			FollowingURI:            "http://localhost:8080/users/1happyturtle/following", | ||||||
| 			FeaturedCollectionURI:   "http://localhost:8080/users/1happyturtle/collections/featured", | 			FeaturedCollectionURI:   "http://localhost:8080/users/1happyturtle/collections/featured", | ||||||
| 			ActorType:               gtsmodel.ActivityStreamsPerson, | 			ActorType:               ap.ActorPerson, | ||||||
| 			AlsoKnownAs:             "", | 			AlsoKnownAs:             "", | ||||||
| 			PrivateKey:              &rsa.PrivateKey{}, | 			PrivateKey:              &rsa.PrivateKey{}, | ||||||
| 			PublicKey:               &rsa.PublicKey{}, | 			PublicKey:               &rsa.PublicKey{}, | ||||||
|  | @ -440,7 +441,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account { | ||||||
| 			FollowersURI:          "http://fossbros-anonymous.io/users/foss_satan/followers", | 			FollowersURI:          "http://fossbros-anonymous.io/users/foss_satan/followers", | ||||||
| 			FollowingURI:          "http://fossbros-anonymous.io/users/foss_satan/following", | 			FollowingURI:          "http://fossbros-anonymous.io/users/foss_satan/following", | ||||||
| 			FeaturedCollectionURI: "http://fossbros-anonymous.io/users/foss_satan/collections/featured", | 			FeaturedCollectionURI: "http://fossbros-anonymous.io/users/foss_satan/collections/featured", | ||||||
| 			ActorType:             gtsmodel.ActivityStreamsPerson, | 			ActorType:             ap.ActorPerson, | ||||||
| 			AlsoKnownAs:           "", | 			AlsoKnownAs:           "", | ||||||
| 			PrivateKey:            &rsa.PrivateKey{}, | 			PrivateKey:            &rsa.PrivateKey{}, | ||||||
| 			PublicKey:             &rsa.PublicKey{}, | 			PublicKey:             &rsa.PublicKey{}, | ||||||
|  | @ -814,7 +815,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"admin_account_status_2": { | 		"admin_account_status_2": { | ||||||
| 			ID:                       "01F8MHAAY43M6RJ473VQFCVH37", | 			ID:                       "01F8MHAAY43M6RJ473VQFCVH37", | ||||||
|  | @ -839,7 +840,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_1_status_1": { | 		"local_account_1_status_1": { | ||||||
| 			ID:                       "01F8MHAMCHF6Y650WCRSCP4WMY", | 			ID:                       "01F8MHAMCHF6Y650WCRSCP4WMY", | ||||||
|  | @ -864,7 +865,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_1_status_2": { | 		"local_account_1_status_2": { | ||||||
| 			ID:                       "01F8MHAYFKS4KMXF8K5Y1C0KRN", | 			ID:                       "01F8MHAYFKS4KMXF8K5Y1C0KRN", | ||||||
|  | @ -889,7 +890,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_1_status_3": { | 		"local_account_1_status_3": { | ||||||
| 			ID:                       "01F8MHBBN8120SYH7D5S050MGK", | 			ID:                       "01F8MHBBN8120SYH7D5S050MGK", | ||||||
|  | @ -914,7 +915,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: false, | 				Replyable: false, | ||||||
| 				Likeable:  false, | 				Likeable:  false, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_1_status_4": { | 		"local_account_1_status_4": { | ||||||
| 			ID:                       "01F8MH82FYRXD2RC6108DAJ5HB", | 			ID:                       "01F8MH82FYRXD2RC6108DAJ5HB", | ||||||
|  | @ -940,7 +941,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_1_status_5": { | 		"local_account_1_status_5": { | ||||||
| 			ID:                       "01FCTA44PW9H1TB328S9AQXKDS", | 			ID:                       "01FCTA44PW9H1TB328S9AQXKDS", | ||||||
|  | @ -966,7 +967,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_2_status_1": { | 		"local_account_2_status_1": { | ||||||
| 			ID:                       "01F8MHBQCBTDKN6X5VHGMMN4MA", | 			ID:                       "01F8MHBQCBTDKN6X5VHGMMN4MA", | ||||||
|  | @ -991,7 +992,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_2_status_2": { | 		"local_account_2_status_2": { | ||||||
| 			ID:                       "01F8MHC0H0A7XHTVH5F596ZKBM", | 			ID:                       "01F8MHC0H0A7XHTVH5F596ZKBM", | ||||||
|  | @ -1016,7 +1017,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: false, | 				Replyable: false, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_2_status_3": { | 		"local_account_2_status_3": { | ||||||
| 			ID:                       "01F8MHC8VWDRBQR0N1BATDDEM5", | 			ID:                       "01F8MHC8VWDRBQR0N1BATDDEM5", | ||||||
|  | @ -1041,7 +1042,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: false, | 				Replyable: false, | ||||||
| 				Likeable:  false, | 				Likeable:  false, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_2_status_4": { | 		"local_account_2_status_4": { | ||||||
| 			ID:                       "01F8MHCP5P2NWYQ416SBA0XSEV", | 			ID:                       "01F8MHCP5P2NWYQ416SBA0XSEV", | ||||||
|  | @ -1066,7 +1067,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 		"local_account_2_status_5": { | 		"local_account_2_status_5": { | ||||||
| 			ID:                       "01FCQSQ667XHJ9AV9T27SJJSX5", | 			ID:                       "01FCQSQ667XHJ9AV9T27SJJSX5", | ||||||
|  | @ -1094,7 +1095,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { | ||||||
| 				Replyable: true, | 				Replyable: true, | ||||||
| 				Likeable:  true, | 				Likeable:  true, | ||||||
| 			}, | 			}, | ||||||
| 			ActivityStreamsType: gtsmodel.ActivityStreamsNote, | 			ActivityStreamsType: ap.ObjectNote, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue