summaryrefslogtreecommitdiff
path: root/internal/processing
diff options
context:
space:
mode:
Diffstat (limited to 'internal/processing')
-rw-r--r--internal/processing/filters/v2/create.go23
-rw-r--r--internal/processing/filters/v2/update.go151
2 files changed, 164 insertions, 10 deletions
diff --git a/internal/processing/filters/v2/create.go b/internal/processing/filters/v2/create.go
index d429e1139..7095a643c 100644
--- a/internal/processing/filters/v2/create.go
+++ b/internal/processing/filters/v2/create.go
@@ -63,6 +63,29 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form
}
}
+ for _, formKeyword := range form.Keywords {
+ filterKeyword := &gtsmodel.FilterKeyword{
+ ID: id.NewULID(),
+ AccountID: account.ID,
+ FilterID: filter.ID,
+ Filter: filter,
+ Keyword: formKeyword.Keyword,
+ WholeWord: formKeyword.WholeWord,
+ }
+ filter.Keywords = append(filter.Keywords, filterKeyword)
+ }
+
+ for _, formStatus := range form.Statuses {
+ filterStatus := &gtsmodel.FilterStatus{
+ ID: id.NewULID(),
+ AccountID: account.ID,
+ FilterID: filter.ID,
+ Filter: filter,
+ StatusID: formStatus.StatusID,
+ }
+ filter.Statuses = append(filter.Statuses, filterStatus)
+ }
+
if err := p.state.DB.PutFilter(ctx, filter); err != nil {
if errors.Is(err, db.ErrAlreadyExists) {
err = errors.New("duplicate title, keyword, or status")
diff --git a/internal/processing/filters/v2/update.go b/internal/processing/filters/v2/update.go
index 5322f63d9..d8297de38 100644
--- a/internal/processing/filters/v2/update.go
+++ b/internal/processing/filters/v2/update.go
@@ -27,6 +27,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/internal/id"
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
"github.com/superseriousbusiness/gotosocial/internal/util"
)
@@ -39,6 +40,8 @@ func (p *Processor) Update(
filterID string,
form *apimodel.FilterUpdateRequestV2,
) (*apimodel.FilterV2, gtserror.WithCode) {
+ var errWithCode gtserror.WithCode
+
// Get the filter by ID, with existing keywords and statuses.
filter, err := p.state.DB.GetFilterByID(ctx, filterID)
if err != nil {
@@ -103,13 +106,17 @@ func (p *Processor) Update(
}
}
- // Temporarily detach keywords and statuses from filter, since we're not updating them below.
- filterKeywords := filter.Keywords
- filterStatuses := filter.Statuses
- filter.Keywords = nil
- filter.Statuses = nil
+ filterKeywordColumns, deleteFilterKeywordIDs, errWithCode := applyKeywordChanges(filter, form.Keywords)
+ if err != nil {
+ return nil, errWithCode
+ }
- if err := p.state.DB.UpdateFilter(ctx, filter, filterColumns, nil, nil, nil); err != nil {
+ deleteFilterStatusIDs, errWithCode := applyStatusChanges(filter, form.Statuses)
+ if err != nil {
+ return nil, errWithCode
+ }
+
+ if err := p.state.DB.UpdateFilter(ctx, filter, filterColumns, filterKeywordColumns, deleteFilterKeywordIDs, deleteFilterStatusIDs); err != nil {
if errors.Is(err, db.ErrAlreadyExists) {
err = errors.New("you already have a filter with this title")
return nil, gtserror.NewErrorConflict(err, err.Error())
@@ -117,10 +124,6 @@ func (p *Processor) Update(
return nil, gtserror.NewErrorInternalError(err)
}
- // Re-attach keywords and statuses before returning.
- filter.Keywords = filterKeywords
- filter.Statuses = filterStatuses
-
apiFilter, errWithCode := p.apiFilter(ctx, filter)
if errWithCode != nil {
return nil, errWithCode
@@ -131,3 +134,131 @@ func (p *Processor) Update(
return apiFilter, nil
}
+
+// applyKeywordChanges applies the provided changes to the filter's keywords in place,
+// and returns a list of lists of filter columns to update, and a list of filter keyword IDs to delete.
+func applyKeywordChanges(filter *gtsmodel.Filter, formKeywords []apimodel.FilterKeywordCreateUpdateDeleteRequest) ([][]string, []string, gtserror.WithCode) {
+ if len(formKeywords) == 0 {
+ // Detach currently existing keywords from the filter so we don't change them.
+ filter.Keywords = nil
+ return nil, nil, nil
+ }
+
+ deleteFilterKeywordIDs := []string{}
+ filterKeywordsByID := map[string]*gtsmodel.FilterKeyword{}
+ filterKeywordColumnsByID := map[string][]string{}
+ for _, filterKeyword := range filter.Keywords {
+ filterKeywordsByID[filterKeyword.ID] = filterKeyword
+ }
+
+ for _, formKeyword := range formKeywords {
+ if formKeyword.ID != nil {
+ id := *formKeyword.ID
+ filterKeyword, ok := filterKeywordsByID[id]
+ if !ok {
+ return nil, nil, gtserror.NewErrorNotFound(
+ fmt.Errorf("couldn't find filter keyword '%s' to update or delete", id),
+ )
+ }
+
+ // Process deletes.
+ if *formKeyword.Destroy {
+ delete(filterKeywordsByID, id)
+ deleteFilterKeywordIDs = append(deleteFilterKeywordIDs, id)
+ continue
+ }
+
+ // Process updates.
+ columns := make([]string, 0, 2)
+ if formKeyword.Keyword != nil {
+ columns = append(columns, "keyword")
+ filterKeyword.Keyword = *formKeyword.Keyword
+ }
+ if formKeyword.WholeWord != nil {
+ columns = append(columns, "whole_word")
+ filterKeyword.WholeWord = formKeyword.WholeWord
+ }
+ filterKeywordColumnsByID[id] = columns
+ continue
+ }
+
+ // Process creates.
+ filterKeyword := &gtsmodel.FilterKeyword{
+ ID: id.NewULID(),
+ AccountID: filter.AccountID,
+ FilterID: filter.ID,
+ Filter: filter,
+ Keyword: *formKeyword.Keyword,
+ WholeWord: util.Ptr(util.PtrValueOr(formKeyword.WholeWord, false)),
+ }
+ filterKeywordsByID[filterKeyword.ID] = filterKeyword
+ // Don't need to set columns, as we're using all of them.
+ }
+
+ // Replace the filter's keywords list with our updated version.
+ filterKeywordColumns := [][]string{}
+ filter.Keywords = nil
+ for id, filterKeyword := range filterKeywordsByID {
+ filter.Keywords = append(filter.Keywords, filterKeyword)
+ // Okay to use the nil slice zero value for entries being created instead of updated.
+ filterKeywordColumns = append(filterKeywordColumns, filterKeywordColumnsByID[id])
+ }
+
+ return filterKeywordColumns, deleteFilterKeywordIDs, nil
+}
+
+// applyKeywordChanges applies the provided changes to the filter's keywords in place,
+// and returns a list of filter status IDs to delete.
+func applyStatusChanges(filter *gtsmodel.Filter, formStatuses []apimodel.FilterStatusCreateDeleteRequest) ([]string, gtserror.WithCode) {
+ if len(formStatuses) == 0 {
+ // Detach currently existing statuses from the filter so we don't change them.
+ filter.Statuses = nil
+ return nil, nil
+ }
+
+ deleteFilterStatusIDs := []string{}
+ filterStatusesByID := map[string]*gtsmodel.FilterStatus{}
+ for _, filterStatus := range filter.Statuses {
+ filterStatusesByID[filterStatus.ID] = filterStatus
+ }
+
+ for _, formStatus := range formStatuses {
+ if formStatus.ID != nil {
+ id := *formStatus.ID
+ _, ok := filterStatusesByID[id]
+ if !ok {
+ return nil, gtserror.NewErrorNotFound(
+ fmt.Errorf("couldn't find filter status '%s' to delete", id),
+ )
+ }
+
+ // Process deletes.
+ if *formStatus.Destroy {
+ delete(filterStatusesByID, id)
+ deleteFilterStatusIDs = append(deleteFilterStatusIDs, id)
+ continue
+ }
+
+ // Filter statuses don't have updates.
+ continue
+ }
+
+ // Process creates.
+ filterStatus := &gtsmodel.FilterStatus{
+ ID: id.NewULID(),
+ AccountID: filter.AccountID,
+ FilterID: filter.ID,
+ Filter: filter,
+ StatusID: *formStatus.StatusID,
+ }
+ filterStatusesByID[filterStatus.ID] = filterStatus
+ }
+
+ // Replace the filter's keywords list with our updated version.
+ filter.Statuses = nil
+ for _, filterStatus := range filterStatusesByID {
+ filter.Statuses = append(filter.Statuses, filterStatus)
+ }
+
+ return deleteFilterStatusIDs, nil
+}