gotosocial/internal/subscriptions/subscriptions.go
2024-12-24 18:05:20 +01:00

159 lines
4.3 KiB
Go

// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package subscriptions
import (
"context"
"encoding/csv"
"errors"
"time"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/state"
"github.com/superseriousbusiness/gotosocial/internal/transport"
"github.com/superseriousbusiness/gotosocial/internal/util"
)
type Subscriptions struct {
state *state.State
transportController transport.Controller
}
func (s *Subscriptions) UpdateDomainPermissions(
ctx context.Context,
permType gtsmodel.DomainPermissionType,
) {
l := log.
WithContext(ctx).
WithField("permType", permType.String())
l.Info("start")
// Get permission subscriptions in priority order (highest -> lowest).
permSubs, err := s.state.DB.GetDomainPermissionSubscriptionsByPriority(ctx, permType)
if err != nil && !errors.Is(err, db.ErrNoEntries) {
// Real db error.
l.Error(err)
return
}
if len(permSubs) == 0 {
// No subscriptions of this
// type, so nothing to do.
return
}
// Get a transport using the instance account,
// we can reuse this for each HTTP call.
tsport, err := s.transportController.NewTransportForUsername(ctx, "")
if err != nil {
l.Error(err)
return
}
for i, permSub := range permSubs {
// Set FetchedAt as we're
// going to attempt this now.
permSub.FetchedAt = time.Now()
columns := []string{"fetched_at"}
// Call the URI but don't force.
resp, err := tsport.DereferenceDomainPermissions(
ctx, permSub, false,
)
if err != nil {
// Bollocks, couldn't get this one.
// Just save the error in the db
// for later perusal by admin.
permSub.Error = err.Error()
columns = append(columns, "error")
if err := s.state.DB.UpdateDomainPermissionSubscription(
ctx, permSub, columns...,
); err != nil {
// Real db error.
l.Error(err)
return
}
// Skip to the
// next permSub.
continue
}
// If the permissions at URI weren't modified
// since last time, just update some metadata
// and call this a successful fetch.
if resp.Unmodified {
permSub.SuccessfullyFetchedAt = time.Now()
columns = append(columns, "successfully_fetched_at")
if permSub.ETag == "" && resp.ETag != "" {
// We didn't have an ETag before but
// we have one now: probably the remote
// added ETag support in the meantime.
permSub.ETag = resp.ETag
columns = append(columns, "etag")
}
if err := s.state.DB.UpdateDomainPermissionSubscription(
ctx, permSub, columns...,
); err != nil {
// Real db error.
l.Error(err)
return
}
// Skip to the
// next permSub.
continue
}
// At this point we know we got a 200 OK from
// the URI, so we've got a live body. Make sure
// we close it when done, wrapping the close func
// with DoOnce for more granular control.
close := util.DoOnce(func() { resp.Body.Close() })
defer close()
// Try to parse the body as a
// list of domain permissions.
switch permSub.ContentType {
// text/csv
case gtsmodel.DomainPermSubContentTypeCSV:
records, err := csv.NewReader(resp.Body).ReadAll()
if err != nil {
}
// application/json
case gtsmodel.DomainPermSubContentTypeJSON:
// text/plain
case gtsmodel.DomainPermSubContentTypePlain:
}
// Slice of permission subscriptions that have
// a higher priority than this one. We should
// not override perms if they already exist
// under a higher-priority subscription.
higherPrios := permSubs[:i]
}
}