From 0ee0210eef23cb650451adc8945daa5de55f00fe Mon Sep 17 00:00:00 2001 From: soxx Date: Mon, 16 Oct 2023 21:48:14 +0200 Subject: [PATCH] feat: added tag support --- example/lowlevel/tag.go | 65 ++++++++++++++++++++ pkg/e621/endpoints/tag.go | 109 +++++++++++++++++++++++++++++++++ pkg/e621/endpoints/tag_test.go | 53 ++++++++++++++++ pkg/e621/endpoints/tags.go | 20 ------ pkg/e621/model/tag.go | 13 ++++ 5 files changed, 240 insertions(+), 20 deletions(-) create mode 100644 example/lowlevel/tag.go create mode 100644 pkg/e621/endpoints/tag.go create mode 100644 pkg/e621/endpoints/tag_test.go delete mode 100644 pkg/e621/endpoints/tags.go create mode 100644 pkg/e621/model/tag.go diff --git a/example/lowlevel/tag.go b/example/lowlevel/tag.go new file mode 100644 index 0000000..b7c0027 --- /dev/null +++ b/example/lowlevel/tag.go @@ -0,0 +1,65 @@ +package main + +import ( + "git.dragse.it/anthrove/e621-to-graph/pkg/e621/endpoints" + "git.dragse.it/anthrove/e621-to-graph/pkg/e621/model" + "log" + "net/http" +) + +func main() { + requestContext := model.RequestContext{ + Host: "https://e621.net", + UserAgent: "Go-e621-SDK (selloo)", + Username: "selloo", + APIKey: "XTkB5doD22vmMXr3yoNurQGH", + } + + log.Println("Getting single tag: ") + client := http.Client{} + tag, err := endpoints.GetTag(client, requestContext, "1530") + if err != nil { + log.Println(err) + } + log.Println(tag.Name) + log.Println("----------") + + log.Println("Getting list of tags: ") + query := map[string]string{ + "limit": "5", + } + + tagList, err := endpoints.GetTags(client, requestContext, query) + if err != nil { + log.Println(err) + } + log.Println(len(tagList)) + log.Println("----------") + + log.Println("seach for tags containing cat: ") + query = map[string]string{ + "limit": "5", + "search[name_matches]": "cat*", + } + + tagList, err = endpoints.GetTags(client, requestContext, query) + if err != nil { + log.Println(err) + } + log.Println(tagList) + log.Println("----------") + + log.Println("seach for tags with the category artist: ") + query = map[string]string{ + "limit": "5", + "search[category]": "1", + } + + tagList, err = endpoints.GetTags(client, requestContext, query) + if err != nil { + log.Println(err) + } + log.Println(tagList) + log.Println("----------") + +} diff --git a/pkg/e621/endpoints/tag.go b/pkg/e621/endpoints/tag.go new file mode 100644 index 0000000..7a67e62 --- /dev/null +++ b/pkg/e621/endpoints/tag.go @@ -0,0 +1,109 @@ +package endpoints + +import ( + "encoding/json" + "fmt" + "git.dragse.it/anthrove/e621-to-graph/internal/utils" + "git.dragse.it/anthrove/e621-to-graph/pkg/e621/model" + "log" + "net/http" +) + +// GetTag allows you to get a tag by ID +func GetTag(client http.Client, requestContext model.RequestContext, ID string) (model.Tag, error) { + + // Create a new HTTP GET request to fetch Tag information from the specified 'host' and 'ID'. + r, err := http.NewRequest("GET", fmt.Sprintf("%s/tags/%s.json", requestContext.Host, ID), nil) + if err != nil { + // Log the error and return an empty Tag struct and the error. + log.Println(err) + return model.Tag{}, err + } + + r.Header.Set("User-Agent", requestContext.UserAgent) + r.Header.Add("Accept", "application/json") + r.SetBasicAuth(requestContext.Username, requestContext.APIKey) + + // Send the request using the provided HTTP client. + resp, err := client.Do(r) + if err != nil { + // Log the error and return an empty Tag struct and the error. + log.Println(err) + return model.Tag{}, err + } + + // Check if the HTTP response status code indicates success (2xx range). + if resp.StatusCode < 200 || resp.StatusCode > 300 { + // If the status code is outside the 2xx range, return an error based on the status code. + return model.Tag{}, utils.StatusCodesToError(resp.StatusCode) + } + + // Initialize a Tag struct to store the response data. + var tag model.Tag + + // Decode the JSON response into the Tag struct. + err = json.NewDecoder(resp.Body).Decode(&tag) + if err != nil { + // Log the error and return an empty Tag struct and the error. + log.Println(err) + return model.Tag{}, err + } + + // Return the Tag information and no error (nil). + return tag, nil +} + +// GetTags allows you to search based on the following query: +// +// - search[name_matches]: A tag name expression to match against, which can include * as a wildcard. +// - search[category]: Filters results to a particular category. Default value is blank (show all tags). See below for allowed values. +// - 0 general; 1 artist; 3 copyright; 4 character; 5 species; 6 invalid; 7 meta; 8 lore +// - search[order]: Changes the sort order. Pass one of date (default), count, or name. +// - search[hide_empty]: Hide tags with zero visible posts. Pass true (default) or false. +// - search[has_wiki]: Show only tags with, or without, a wiki page. Pass true, false, or blank (default). +// - search[has_artist]: Show only tags with, or without an artist page. Pass true, false, or blank (default). +// - limit: Maximum number of results to return per query. Default is 75. There is a hard upper limit of 320. +// - page: The page that will be returned. Can also be used with a or b + tag_id to get the tags after or before the specified tag ID. For example a13 gets every tag after tag_id 13 up to the limit. This overrides the specified search ordering, date is always used instead. +func GetTags(client http.Client, requestContext model.RequestContext, query map[string]string) ([]model.Tag, error) { + // Create a new HTTP GET request. + r, err := http.NewRequest("GET", fmt.Sprintf("%s/tags.json", requestContext.Host), nil) + if err != nil { + log.Print(err) + } + + // Append query parameters to the request URL. + q := r.URL.Query() + for k, v := range query { + q.Add(k, v) + } + r.URL.RawQuery = q.Encode() + + r.Header.Set("User-Agent", requestContext.UserAgent) + r.Header.Add("Accept", "application/json") + r.SetBasicAuth(requestContext.Username, requestContext.APIKey) + + // Send the request using the provided HTTP client. + resp, err := client.Do(r) + if err != nil { + log.Print(err) + } + + // Check if the HTTP response status code indicates success (2xx range). + if resp.StatusCode < 200 || resp.StatusCode > 300 { + // If the status code is outside the 2xx range, return an error based on the status code. + return []model.Tag{}, utils.StatusCodesToError(resp.StatusCode) + } + + // Initialize a Tag struct to store the response data. + var tag []model.Tag + + // Decode the JSON response into the user struct. + err = json.NewDecoder(resp.Body).Decode(&tag) + if err != nil { + // Log the error and return an empty Tag struct and the error. + log.Println(err) + return []model.Tag{}, err + } + + return tag, nil +} diff --git a/pkg/e621/endpoints/tag_test.go b/pkg/e621/endpoints/tag_test.go new file mode 100644 index 0000000..655853e --- /dev/null +++ b/pkg/e621/endpoints/tag_test.go @@ -0,0 +1,53 @@ +package endpoints + +import ( + "git.dragse.it/anthrove/e621-to-graph/pkg/e621/model" + "github.com/jarcoal/httpmock" + "net/http" + "testing" +) + +func TestGetTag(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + tagResponse := model.Tag{ + ID: 165165, + Name: "35ad13", + PostCount: 59, + RelatedTags: "[]", + RelatedTagsUpdatedAt: "2023-10-16T07:58:15.897+02:00", + Category: 0, + IsLocked: false, + CreatedAt: "2023-10-16T07:58:15.917+02:00", + UpdatedAt: "2023-10-16T07:58:23.310+02:00", + } + + jsonResponser, err := httpmock.NewJsonResponder(200, tagResponse) + if err != nil { + t.Error(err) + return + } + httpmock.RegisterResponder("GET", "https://e621.net/tags/165165.json", jsonResponser) + + requestContext := model.RequestContext{ + Host: "https://e621.net", + UserAgent: "Go-e621-SDK (@username)", + Username: "memo", + APIKey: "123456", + } + + client := http.Client{} + tag, err := GetTag(client, requestContext, "165165") + if err != nil { + t.Error(err) + return + } + + if tag.ID == tagResponse.ID && tag.Name == tagResponse.Name && tag.CreatedAt == tag.CreatedAt { + return + } + + t.Errorf("Respons did not match mock data:\nOriginal: %v\nMock: %v", tag, tagResponse) + +} diff --git a/pkg/e621/endpoints/tags.go b/pkg/e621/endpoints/tags.go deleted file mode 100644 index dedbe0a..0000000 --- a/pkg/e621/endpoints/tags.go +++ /dev/null @@ -1,20 +0,0 @@ -package endpoints - -import ( - "git.dragse.it/anthrove/e621-to-graph/pkg/e621/model" - "net/http" -) - -// GetTags allows you to search based on the following query: -// -// - search[name_matches]: A tag name expression to match against, which can include * as a wildcard. -// - search[category]: Filters results to a particular category. Default value is blank (show all tags). See below for allowed values. -// - search[order]: Changes the sort order. Pass one of date (default), count, or name. -// - search[hide_empty]: Hide tags with zero visible posts. Pass true (default) or false. -// - search[has_wiki]: Show only tags with, or without, a wiki page. Pass true, false, or blank (default). -// - search[has_artist]: Show only tags with, or without an artist page. Pass true, false, or blank (default). -// - limit: Maximum number of results to return per query. Default is 75. There is a hard upper limit of 320. -// - page: The page that will be returned. Can also be used with a or b + tag_id to get the tags after or before the specified tag ID. For example a13 gets every tag after tag_id 13 up to the limit. This overrides the specified search ordering, date is always used instead. -func GetTags(client http.Client, requestContext model.RequestContext, query map[string]string) { - return -} diff --git a/pkg/e621/model/tag.go b/pkg/e621/model/tag.go new file mode 100644 index 0000000..f084af2 --- /dev/null +++ b/pkg/e621/model/tag.go @@ -0,0 +1,13 @@ +package model + +type Tag struct { + ID int64 `json:"id"` + Name string `json:"name"` + PostCount int64 `json:"post_count"` + RelatedTags string `json:"related_tags"` + RelatedTagsUpdatedAt string `json:"related_tags_updated_at"` + Category int64 `json:"category"` + IsLocked bool `json:"is_locked"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +}