diff --git a/mastodon.go b/mastodon.go index c704e10..942e1d0 100644 --- a/mastodon.go +++ b/mastodon.go @@ -251,13 +251,6 @@ type Mention struct { ID ID `json:"id"` } -// Tag hold information for tag. -type Tag struct { - Name string `json:"name"` - URL string `json:"url"` - History []History `json:"history"` -} - // History hold information for history. type History struct { Day string `json:"day"` diff --git a/tags.go b/tags.go new file mode 100644 index 0000000..97ba820 --- /dev/null +++ b/tags.go @@ -0,0 +1,55 @@ +package mastodon + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// Tag hold information for tag. +type Tag struct { + Name string `json:"name"` + URL string `json:"url"` + History []History `json:"history"` + Following interface{} `json:"following"` +} + +// TagInfo gets statistics and information about a tag +func (c *Client) TagInfo(ctx context.Context, tag string) (*Tag, error) { + var hashtag Tag + err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/tags/%s", url.PathEscape(string(tag))), nil, &hashtag, nil) + if err != nil { + return nil, err + } + return &hashtag, nil +} + +// TagFollow lets you follow a hashtag +func (c *Client) TagFollow(ctx context.Context, tag string) (*Tag, error) { + var hashtag Tag + err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/tags/%s/follow", url.PathEscape(string(tag))), nil, &hashtag, nil) + if err != nil { + return nil, err + } + return &hashtag, nil +} + +// TagUnfollow lets you unfollow a hashtag +func (c *Client) TagUnfollow(ctx context.Context, tag string) (*Tag, error) { + var hashtag Tag + err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/tags/%s/unfollow", url.PathEscape(string(tag))), nil, &hashtag, nil) + if err != nil { + return nil, err + } + return &hashtag, nil +} + +func (c *Client) TagsFollowed(ctx context.Context, pg *Pagination) ([]*Tag, error) { + var hashtags []*Tag + err := c.doAPI(ctx, http.MethodGet, "/api/v1/followed_tags", nil, &hashtags, pg) + if err != nil { + return nil, err + } + return hashtags, nil +} diff --git a/tags_test.go b/tags_test.go new file mode 100644 index 0000000..dc1e9e9 --- /dev/null +++ b/tags_test.go @@ -0,0 +1,276 @@ +package mastodon + +import ( + "context" + "fmt" + "net/http" + "net/http/httptest" + "testing" +) + +func TestTagInfo(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/tags/test" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + fmt.Fprintln(w, ` + { + "name": "test", + "url": "http://mastodon.example/tags/test", + "history": [ + { + "day": "1668124800", + "accounts": "1", + "uses": "2" + }, + { + "day": "1668038400", + "accounts": "0", + "uses": "0" + } + ] + }`) + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + _, err := client.TagInfo(context.Background(), "foo") + if err == nil { + t.Fatalf("should be fail: %v", err) + } + tag, err := client.TagInfo(context.Background(), "test") + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if tag.Name != "test" { + t.Fatalf("want %q but %q", "test", tag.Name) + } + if tag.URL != "http://mastodon.example/tags/test" { + t.Fatalf("want %q but %q", "http://mastodon.example/tags/test", tag.URL) + } + if len(tag.History) != 2 { + t.Fatalf("result should be two: %d", len(tag.History)) + } + if tag.History[0].Day != "1668124800" { + t.Fatalf("want %q but %q", "1668124800", tag.History[0].Day) + } + if tag.History[0].Accounts != "1" { + t.Fatalf("want %q but %q", "1", tag.History[0].Accounts) + } + if tag.History[0].Uses != "2" { + t.Fatalf("want %q but %q", "2", tag.History[0].Uses) + } + if tag.Following != nil { + t.Fatalf("want %v but %q", nil, tag.Following) + } +} + +func TestTagFollow(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/tags/test/follow" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + fmt.Fprintln(w, ` + { + "name": "test", + "url": "http://mastodon.example/tags/test", + "history": [ + { + "day": "1668124800", + "accounts": "1", + "uses": "2" + }, + { + "day": "1668038400", + "accounts": "0", + "uses": "0" + } + ], + "following": true + }`) + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + _, err := client.TagFollow(context.Background(), "foo") + if err == nil { + t.Fatalf("should be fail: %v", err) + } + tag, err := client.TagFollow(context.Background(), "test") + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if tag.Name != "test" { + t.Fatalf("want %q but %q", "test", tag.Name) + } + if tag.URL != "http://mastodon.example/tags/test" { + t.Fatalf("want %q but %q", "http://mastodon.example/tags/test", tag.URL) + } + if len(tag.History) != 2 { + t.Fatalf("result should be two: %d", len(tag.History)) + } + if tag.History[0].Day != "1668124800" { + t.Fatalf("want %q but %q", "1668124800", tag.History[0].Day) + } + if tag.History[0].Accounts != "1" { + t.Fatalf("want %q but %q", "1", tag.History[0].Accounts) + } + if tag.History[0].Uses != "2" { + t.Fatalf("want %q but %q", "2", tag.History[0].Uses) + } + if tag.Following != true { + t.Fatalf("want %v but %q", true, tag.Following) + } +} + +func TestTagUnfollow(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/tags/test/follow" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + fmt.Fprintln(w, ` + { + "name": "test", + "url": "http://mastodon.example/tags/test", + "history": [ + { + "day": "1668124800", + "accounts": "1", + "uses": "2" + }, + { + "day": "1668038400", + "accounts": "0", + "uses": "0" + } + ], + "following": false + }`) + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + _, err := client.TagFollow(context.Background(), "foo") + if err == nil { + t.Fatalf("should be fail: %v", err) + } + tag, err := client.TagFollow(context.Background(), "test") + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if tag.Name != "test" { + t.Fatalf("want %q but %q", "test", tag.Name) + } + if tag.URL != "http://mastodon.example/tags/test" { + t.Fatalf("want %q but %q", "http://mastodon.example/tags/test", tag.URL) + } + if len(tag.History) != 2 { + t.Fatalf("result should be two: %d", len(tag.History)) + } + if tag.History[0].Day != "1668124800" { + t.Fatalf("want %q but %q", "1668124800", tag.History[0].Day) + } + if tag.History[0].Accounts != "1" { + t.Fatalf("want %q but %q", "1", tag.History[0].Accounts) + } + if tag.History[0].Uses != "2" { + t.Fatalf("want %q but %q", "2", tag.History[0].Uses) + } + if tag.Following != false { + t.Fatalf("want %v but %q", false, tag.Following) + } +} + +func TestTagsFollowed(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, ` + [{ + "name": "test", + "url": "http://mastodon.example/tags/test", + "history": [ + { + "day": "1668124800", + "accounts": "1", + "uses": "2" + }, + { + "day": "1668038400", + "accounts": "0", + "uses": "0" + } + ], + "following": true + }, + { + "name": "foo", + "url": "http://mastodon.example/tags/foo", + "history": [ + { + "day": "1668124800", + "accounts": "1", + "uses": "2" + }, + { + "day": "1668038400", + "accounts": "0", + "uses": "0" + } + ], + "following": true + }]`) + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + tags, err := client.TagsFollowed(context.Background(), nil) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if len(tags) != 2 { + t.Fatalf("want %q but %q", 2, len(tags)) + } + if tags[0].Name != "test" { + t.Fatalf("want %q but %q", "test", tags[0].Name) + } + if tags[0].URL != "http://mastodon.example/tags/test" { + t.Fatalf("want %q but %q", "http://mastodon.example/tags/test", tags[0].URL) + } + if len(tags[0].History) != 2 { + t.Fatalf("result should be two: %d", len(tags[0].History)) + } + if tags[0].History[0].Day != "1668124800" { + t.Fatalf("want %q but %q", "1668124800", tags[0].History[0].Day) + } + if tags[0].History[0].Accounts != "1" { + t.Fatalf("want %q but %q", "1", tags[0].History[0].Accounts) + } + if tags[0].History[0].Uses != "2" { + t.Fatalf("want %q but %q", "2", tags[0].History[0].Uses) + } + if tags[0].Following != true { + t.Fatalf("want %v but %q", nil, tags[0].Following) + } +}