diff --git a/go.mod b/go.mod index 01a687c..b5fd79a 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,9 @@ module git.anthrove.art/Anthrove/gorse-playground go 1.23.0 -require github.com/caarlos0/env/v11 v11.3.1 // indirect +require ( + github.com/anthrove/openapi-e621-go v1.1.2 // indirect + github.com/caarlos0/env/v11 v11.3.1 // indirect + golang.org/x/time v0.9.0 // indirect + gopkg.in/validator.v2 v2.0.1 // indirect +) diff --git a/go.sum b/go.sum index 1724948..10cc3dd 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,8 @@ +github.com/anthrove/openapi-e621-go v1.1.2 h1:x+zYGb9zi5QgHvlhtnwhOJtFgC7DONBfgH7Bc2TDw8w= +github.com/anthrove/openapi-e621-go v1.1.2/go.mod h1:CET4X8hWfC1O1APRB2pHjbP4FwRyde6t4EaimijJCG0= github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA= github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +gopkg.in/validator.v2 v2.0.1 h1:xF0KWyGWXm/LM2G1TrEjqOu4pa6coO9AlWSf3msVfDY= +gopkg.in/validator.v2 v2.0.1/go.mod h1:lIUZBlB3Im4s/eYp39Ry/wkR02yOPhZ9IwIRBjuPuG8= diff --git a/internal/config/gorse.go b/internal/config/gorse.go new file mode 100644 index 0000000..db08e99 --- /dev/null +++ b/internal/config/gorse.go @@ -0,0 +1,6 @@ +package config + +type Gorse struct { + Endpoint string `env:"GORSE_ENDPOINT"` + ApiKey string `env:"GORSE_APIKEY"` +} diff --git a/internal/logic/e621.go b/internal/logic/e621.go index 4c79103..e280cb7 100644 --- a/internal/logic/e621.go +++ b/internal/logic/e621.go @@ -1 +1,99 @@ package logic + +import ( + "context" + "encoding/base64" + "fmt" + "git.anthrove.art/Anthrove/gorse-playground/internal/config" + "github.com/anthrove/openapi-e621-go" + "github.com/caarlos0/env/v11" + "golang.org/x/time/rate" + "log" + "net/http" +) + +var e621Config config.E621 +var rateLimit *rate.Limiter +var apiClient *openapi.APIClient + +func init() { + err := env.Parse(&e621Config) + + if err != nil { + log.Panic(err) + } + + rateLimit = rate.NewLimiter(1, 2) + + apiClient, err = newE621Client(e621Config) + + if err != nil { + log.Panic(err) + } + +} + +func newE621Client(cfg config.E621) (*openapi.APIClient, error) { + e621Config := openapi.NewConfiguration() + e621Config.DefaultHeader["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte(cfg.Username+":"+cfg.ApiKey)) + e621Config.UserAgent = fmt.Sprintf("gorse-playground-scraper used by %s | (made by the Anthrove Team)", cfg.Username) + e621Config.Debug = false + + client := http.DefaultClient + client.Transport = newRateMiddleware(&http.Transport{}) + + e621Config.HTTPClient = client + + return openapi.NewAPIClient(e621Config), nil +} + +func GetAllFavorites(ctx context.Context, userID int) ([]openapi.Post, error) { + posts := make([]openapi.Post, 0) + + page := 1 + for { + currentFavs, err := GetFavoritePage(ctx, userID, page) + + if err != nil { + return nil, err + } + + if len(currentFavs) == 0 { + break + } + + posts = append(posts, currentFavs...) + page++ + } + + return posts, nil +} + +func GetFavoritePage(ctx context.Context, userId int, pageIdentifier int) ([]openapi.Post, error) { + favorites, _, err := apiClient.FavoritesAPI.ListFavorites(ctx).Page(int32(pageIdentifier)).UserId(int32(userId)).Execute() + if err != nil { + return make([]openapi.Post, 0), err + } + + return favorites.Posts, nil +} + +func newRateMiddleware(transport *http.Transport) http.RoundTripper { + return &rateMiddleware{ + transport: transport, + } +} + +type rateMiddleware struct { + transport *http.Transport +} + +func (r rateMiddleware) RoundTrip(request *http.Request) (*http.Response, error) { + err := rateLimit.Wait(request.Context()) + + if err != nil { + return nil, err + } + + return r.transport.RoundTrip(request) +} diff --git a/internal/logic/gorse.go b/internal/logic/gorse.go new file mode 100644 index 0000000..5972c5b --- /dev/null +++ b/internal/logic/gorse.go @@ -0,0 +1,49 @@ +package logic + +import ( + "bytes" + "context" + "encoding/json" + "git.anthrove.art/Anthrove/gorse-playground/internal/config" + "git.anthrove.art/Anthrove/gorse-playground/pkg/models" + "github.com/caarlos0/env/v11" + "log" + "net/http" +) + +var gorseConfig config.Gorse + +func init() { + err := env.Parse(&gorseConfig) + + if err != nil { + log.Panic(err) + } +} + +func UpsertUser(ctx context.Context, user models.GorseUser) error { + return executeRequest(ctx, http.MethodPost, "/api/user", user) +} + +func executeRequest(ctx context.Context, method, url string, data any) error { + jsonData, err := json.Marshal(data) + + if err != nil { + return err + } + + client := &http.Client{} + req, err := http.NewRequest(method, gorseConfig.Endpoint+url, bytes.NewReader(jsonData)) + if err != nil { + return err + } + req = req.WithContext(ctx) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-API-Key", gorseConfig.ApiKey) + _, err = client.Do(req) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/models/gorse.go b/pkg/models/gorse.go new file mode 100644 index 0000000..cdc7374 --- /dev/null +++ b/pkg/models/gorse.go @@ -0,0 +1,25 @@ +package models + +type GorseItem struct { + Categories []string `json:"Categories"` + Comment string `json:"Comment"` + IsHidden bool `json:"IsHidden"` + ItemId string `json:"ItemId"` + Labels []string `json:"Labels"` + Timestamp string `json:"Timestamp"` +} + +type GorseFavorite struct { + Comment string `json:"Comment"` + FeedbackType string `json:"FeedbackType"` + ItemId string `json:"ItemId"` + Timestamp string `json:"Timestamp"` + UserId string `json:"UserId"` +} + +type GorseUser struct { + Comment string `json:"Comment"` + Labels []string `json:"Labels"` + Subscribe []string `json:"Subscribe"` + UserId string `json:"UserId"` +}