From ae6cc118205477dc1fd9dee5c2a997df6e8118b2 Mon Sep 17 00:00:00 2001 From: Rasmus Lindroth Date: Fri, 5 Nov 2021 09:21:53 +0100 Subject: [PATCH 1/5] Add support for creating polls --- mastodon.go | 9 +++++++++ status.go | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/mastodon.go b/mastodon.go index d642cf3..3523713 100644 --- a/mastodon.go +++ b/mastodon.go @@ -219,6 +219,15 @@ type Toot struct { SpoilerText string `json:"spoiler_text"` Visibility string `json:"visibility"` ScheduledAt *time.Time `json:"scheduled_at,omitempty"` + Poll *TootPoll `json:"poll"` +} + +// TootPoll holds information for creating a poll in Toot. +type TootPoll struct { + Options []string `json:"options"` + ExpiresInSeconds int64 `json:"expires_in"` + Multiple bool `json:"multiple"` + HideTotals bool `json:"hide_totals"` } // Mention hold information for mention. diff --git a/status.go b/status.go index bd86a15..5cdbf22 100644 --- a/status.go +++ b/status.go @@ -349,6 +349,19 @@ func (c *Client) PostStatus(ctx context.Context, toot *Toot) (*Status, error) { params.Add("media_ids[]", string(media)) } } + // Can't use Media and Poll at the same time. + if toot.Poll != nil && toot.Poll.Options != nil && toot.MediaIDs == nil { + for _, opt := range toot.Poll.Options { + params.Add("poll[options][]", string(opt)) + } + params.Add("poll[expires_in]", fmt.Sprintf("%d", toot.Poll.ExpiresInSeconds)) + if toot.Poll.Multiple { + params.Add("poll[multiple]", "true") + } + if toot.Poll.HideTotals { + params.Add("poll[hide_totals]", "true") + } + } if toot.Visibility != "" { params.Set("visibility", fmt.Sprint(toot.Visibility)) } From 4cbbf813dc0e65993c9450b107701464a5bd5488 Mon Sep 17 00:00:00 2001 From: Rasmus Lindroth Date: Fri, 5 Nov 2021 10:47:57 +0100 Subject: [PATCH 2/5] add test for PostStatus --- mastodon_test.go | 111 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/mastodon_test.go b/mastodon_test.go index ef70981..9a8f3e3 100644 --- a/mastodon_test.go +++ b/mastodon_test.go @@ -2,6 +2,7 @@ package mastodon import ( "context" + "encoding/json" "fmt" "io" "net/http" @@ -204,6 +205,116 @@ func TestPostStatusWithCancel(t *testing.T) { t.Fatalf("want %q but %q", want, err.Error()) } } +func TestPostStatusParams(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/statuses" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + r.ParseForm() + if r.FormValue("media_ids[]") != "" && r.FormValue("poll[options][]") != "" { + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + } + s := Status{ + ID: ID("1"), + Content: fmt.Sprintf("

%s

", r.FormValue("status")), + } + if r.FormValue("in_reply_to_id") != "" { + s.InReplyToID = ID(r.FormValue("in_reply_to_id")) + } + if r.FormValue("visibility") != "" { + s.Visibility = (r.FormValue("visibility")) + } + if r.FormValue("sensitive") == "true" { + s.Sensitive = true + s.SpoilerText = fmt.Sprintf("

%s

", r.FormValue("spoiler_text")) + } + if r.FormValue("media_ids[]") != "" { + for _, id := range r.Form["media_ids[]"] { + s.MediaAttachments = append(s.MediaAttachments, + Attachment{ID: ID(id)}) + } + } + if r.FormValue("poll[options][]") != "" { + p := Poll{} + for _, opt := range r.Form["poll[options][]"] { + p.Options = append(p.Options, PollOption{ + Title: opt, + VotesCount: 0, + }) + } + if r.FormValue("poll[multiple]") == "true" { + p.Multiple = true + } + s.Poll = &p + } + json.NewEncoder(w).Encode(s) + })) + defer ts.Close() + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + s, err := client.PostStatus(context.Background(), &Toot{ + Status: "foobar", + InReplyToID: ID("2"), + Visibility: "unlisted", + Sensitive: true, + SpoilerText: "bar", + MediaIDs: []ID{"1", "2"}, + Poll: &TootPoll{ + Options: []string{"A", "B"}, + }, + }) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if len(s.MediaAttachments) > 0 && s.Poll != nil { + t.Fatal("should not fail, can't have both Media and Poll") + } + if s.Content != "

foobar

" { + t.Fatalf("want %q but %q", "

foobar

", s.Content) + } + if s.InReplyToID != "2" { + t.Fatalf("want %q but %q", "2", s.InReplyToID) + } + if s.Visibility != "unlisted" { + t.Fatalf("want %q but %q", "unlisted", s.Visibility) + } + if s.Sensitive != true { + t.Fatalf("want %t but %t", true, s.Sensitive) + } + if s.SpoilerText != "

bar

" { + t.Fatalf("want %q but %q", "

bar

", s.SpoilerText) + } + s, err = client.PostStatus(context.Background(), &Toot{ + Status: "foobar", + Poll: &TootPoll{ + Multiple: true, + Options: []string{"A", "B"}, + }, + }) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if s.Poll == nil { + t.Fatalf("poll should not be %v", s.Poll) + } + if len(s.Poll.Options) != 2 { + t.Fatalf("want %q but %q", 2, len(s.Poll.Options)) + } + if s.Poll.Options[0].Title != "A" { + t.Fatalf("want %q but %q", "A", s.Poll.Options[0].Title) + } + if s.Poll.Options[1].Title != "B" { + t.Fatalf("want %q but %q", "B", s.Poll.Options[1].Title) + } + if s.Poll.Multiple != true { + t.Fatalf("want %t but %t", true, s.Poll.Multiple) + } +} func TestGetTimelineHome(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { From 62214db600258b785d9d7748f86de799e135736f Mon Sep 17 00:00:00 2001 From: shine <4771718+shinenelson@users.noreply.github.com> Date: Thu, 1 Jul 2021 01:34:28 +0530 Subject: [PATCH 3/5] document bookmark APIs follows d39c10b which introduced the bookmark APIs. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index dbda926..a359189 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ func main() { * [x] GET /api/v1/accounts/:id/lists * [x] GET /api/v1/accounts/relationships * [x] GET /api/v1/accounts/search +* [x] GET /api/v1/bookmarks * [x] POST /api/v1/apps * [x] GET /api/v1/blocks * [x] GET /api/v1/conversations @@ -131,6 +132,8 @@ func main() { * [x] POST /api/v1/statuses/:id/unreblog * [x] POST /api/v1/statuses/:id/favourite * [x] POST /api/v1/statuses/:id/unfavourite +* [x] POST /api/v1/statuses/:id/bookmark +* [x] POST /api/v1/statuses/:id/unbookmark * [x] GET /api/v1/timelines/home * [x] GET /api/v1/timelines/public * [x] GET /api/v1/timelines/tag/:hashtag From 45d75e80853082b98248dc0534314dcac0a68532 Mon Sep 17 00:00:00 2001 From: Marian Steinbach Date: Tue, 23 Nov 2021 09:05:52 +0100 Subject: [PATCH 4/5] Update badge in README to point to pkg.go.dev --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a359189..a60f93f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://github.com/mattn/go-mastodon/workflows/test/badge.svg?branch=master)](https://github.com/mattn/go-mastodon/actions?query=workflow%3Atest) [![Codecov](https://codecov.io/gh/mattn/go-mastodon/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-mastodon) -[![GoDoc](https://godoc.org/github.com/mattn/go-mastodon?status.svg)](http://godoc.org/github.com/mattn/go-mastodon) +[![Go Reference](https://pkg.go.dev/badge/github.com/mattn/go-mastodon.svg)](https://pkg.go.dev/github.com/mattn/go-mastodon) [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-mastodon)](https://goreportcard.com/report/github.com/mattn/go-mastodon) From 7745e19ff7872bcc549eb5e6955dae408fd21acf Mon Sep 17 00:00:00 2001 From: Marian Steinbach Date: Tue, 16 Nov 2021 14:50:42 +0100 Subject: [PATCH 5/5] Only set Authorization header when AccessToken is set --- streaming.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/streaming.go b/streaming.go index f560fd8..2148ed0 100644 --- a/streaming.go +++ b/streaming.go @@ -92,7 +92,10 @@ func (c *Client) streaming(ctx context.Context, p string, params url.Values) (ch return nil, err } req = req.WithContext(ctx) - req.Header.Set("Authorization", "Bearer "+c.Config.AccessToken) + + if c.Config.AccessToken != "" { + req.Header.Set("Authorization", "Bearer "+c.Config.AccessToken) + } q := make(chan Event) go func() {