package pulls import ( "bytes" "compress/gzip" "fmt" "io" "log/slog" "strings" "time" "tangled.org/core/appview/config" "tangled.org/core/appview/db" pulls_indexer "tangled.org/core/appview/indexer/pulls" "tangled.org/core/appview/knotacl" "tangled.org/core/appview/mentions" "tangled.org/core/appview/models" "tangled.org/core/appview/notify" "tangled.org/core/appview/oauth" "tangled.org/core/appview/pages" "tangled.org/core/appview/reporesolver" "tangled.org/core/idresolver" "tangled.org/core/ogre" "tangled.org/core/patchutil" "tangled.org/core/types" indigoxrpc "github.com/bluesky-social/indigo/xrpc" "github.com/hashicorp/golang-lru/v2/expirable" ) const ApplicationGzip = "application/gzip" const ( diffCacheSize = 128 diffCacheTTL = 15 * time.Minute ) type Pulls struct { oauth *oauth.OAuth repoResolver *reporesolver.RepoResolver pages *pages.Pages idResolver *idresolver.Resolver mentionsResolver *mentions.Resolver db *db.DB config *config.Config notifier notify.Notifier acl *knotacl.Service logger *slog.Logger indexer *pulls_indexer.Indexer ogreClient *ogre.Client diffCache *expirable.LRU[string, types.DiffRenderer] } func New( oauth *oauth.OAuth, repoResolver *reporesolver.RepoResolver, pages *pages.Pages, resolver *idresolver.Resolver, mentionsResolver *mentions.Resolver, db *db.DB, config *config.Config, notifier notify.Notifier, acl *knotacl.Service, indexer *pulls_indexer.Indexer, logger *slog.Logger, ) *Pulls { return &Pulls{ oauth: oauth, repoResolver: repoResolver, pages: pages, idResolver: resolver, mentionsResolver: mentionsResolver, db: db, config: config, notifier: notifier, acl: acl, logger: logger, indexer: indexer, ogreClient: ogre.NewClient(config.Ogre.Host), diffCache: expirable.NewLRU[string, types.DiffRenderer](diffCacheSize, nil, diffCacheTTL), } } func (s *Pulls) knotClient(host string) *indigoxrpc.Client { scheme := "https" if s.config.Core.Dev { scheme = "http" } return &indigoxrpc.Client{Host: fmt.Sprintf("%s://%s", scheme, host)} } func gz(s string) io.Reader { var b bytes.Buffer w := gzip.NewWriter(&b) w.Write([]byte(s)) w.Close() return &b } func ptrPullState(s models.PullState) *models.PullState { return &s } func validatePatch(patch *string) error { if patch == nil || *patch == "" { return fmt.Errorf("patch is empty") } // add newline if not present to diff style patches if !patchutil.IsFormatPatch(*patch) && !strings.HasSuffix(*patch, "\n") { *patch = *patch + "\n" } if err := patchutil.IsPatchValid(*patch); err != nil { return err } return nil }