From ea59675755bc873a9bdd7905c353abda318a68c7 Mon Sep 17 00:00:00 2001 From: Rasmus Lindroth Date: Sun, 15 May 2022 20:44:09 +0200 Subject: [PATCH] add new commit --- README.md | 7 ++++++- accounts_test.go | 22 ++++++++++++++++++---- apps_test.go | 2 ++ example_test.go | 2 +- filters_test.go | 4 ---- lists_test.go | 21 +++++++++++++++------ mastodon_test.go | 6 ++++++ notification_test.go | 2 ++ report_test.go | 6 ++++-- status_test.go | 22 ++++++++++++++++++++++ streaming.go | 28 +++++++++++++++++++++++----- streaming_test.go | 39 ++++++++++++++++++++++++--------------- 12 files changed, 123 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 91a1634..2a18429 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,11 @@ func main() { * [x] DELETE /api/v1/conversations/:id * [x] POST /api/v1/conversations/:id/read * [x] GET /api/v1/favourites +* [x] GET /api/v1/filters +* [x] POST /api/v1/filters +* [x] GET /api/v1/filters/:id +* [x] PUT /api/v1/filters/:id +* [x] DELETE /api/v1/filters/:id * [x] GET /api/v1/follow_requests * [x] POST /api/v1/follow_requests/:id/authorize * [x] POST /api/v1/follow_requests/:id/reject @@ -153,7 +158,7 @@ func main() { ## Installation ``` -$ go get github.com/mattn/go-mastodon +$ go get github.com/RasmusLindroth/go-mastodon ``` ## License diff --git a/accounts_test.go b/accounts_test.go index 43a5e3b..4eed9ea 100644 --- a/accounts_test.go +++ b/accounts_test.go @@ -118,6 +118,7 @@ func TestGetAccountStatuses(t *testing.T) { return } fmt.Fprintln(w, `[{"content": "foo"}, {"content": "bar"}]`) + return })) defer ts.Close() @@ -150,6 +151,7 @@ func TestGetAccountFollowers(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -185,6 +187,7 @@ func TestGetAccountFollowing(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -222,6 +225,7 @@ func TestGetBlocks(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -257,6 +261,7 @@ func TestAccountFollow(t *testing.T) { return } fmt.Fprintln(w, `{"id":1234567,"following":true}`) + return })) defer ts.Close() @@ -266,11 +271,11 @@ func TestAccountFollow(t *testing.T) { ClientSecret: "bar", AccessToken: "zoo", }) - _, err := client.AccountFollow(context.Background(), "123") + rel, err := client.AccountFollow(context.Background(), "123") if err == nil { t.Fatalf("should be fail: %v", err) } - rel, err := client.AccountFollow(context.Background(), "1234567") + rel, err = client.AccountFollow(context.Background(), "1234567") if err != nil { t.Fatalf("should not be fail: %v", err) } @@ -289,6 +294,7 @@ func TestAccountUnfollow(t *testing.T) { return } fmt.Fprintln(w, `{"id":1234567,"following":false}`) + return })) defer ts.Close() @@ -298,11 +304,11 @@ func TestAccountUnfollow(t *testing.T) { ClientSecret: "bar", AccessToken: "zoo", }) - _, err := client.AccountUnfollow(context.Background(), "123") + rel, err := client.AccountUnfollow(context.Background(), "123") if err == nil { t.Fatalf("should be fail: %v", err) } - rel, err := client.AccountUnfollow(context.Background(), "1234567") + rel, err = client.AccountUnfollow(context.Background(), "1234567") if err != nil { t.Fatalf("should not be fail: %v", err) } @@ -321,6 +327,7 @@ func TestAccountBlock(t *testing.T) { return } fmt.Fprintln(w, `{"id":1234567,"blocking":true}`) + return })) defer ts.Close() @@ -353,6 +360,7 @@ func TestAccountUnblock(t *testing.T) { return } fmt.Fprintln(w, `{"id":1234567,"blocking":false}`) + return })) defer ts.Close() @@ -385,6 +393,7 @@ func TestAccountMute(t *testing.T) { return } fmt.Fprintln(w, `{"id":1234567,"muting":true}`) + return })) defer ts.Close() @@ -417,6 +426,7 @@ func TestAccountUnmute(t *testing.T) { return } fmt.Fprintln(w, `{"id":1234567,"muting":false}`) + return })) defer ts.Close() @@ -482,6 +492,7 @@ func TestAccountsSearch(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foobar"}, {"username": "barfoo"}]`) + return })) defer ts.Close() @@ -517,6 +528,7 @@ func TestFollowRemoteUser(t *testing.T) { return } fmt.Fprintln(w, `{"username": "zzz"}`) + return })) defer ts.Close() @@ -548,6 +560,7 @@ func TestGetFollowRequests(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -633,6 +646,7 @@ func TestGetMutes(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() diff --git a/apps_test.go b/apps_test.go index d061639..32e28ab 100644 --- a/apps_test.go +++ b/apps_test.go @@ -27,6 +27,7 @@ func TestRegisterApp(t *testing.T) { return } fmt.Fprintln(w, `{"id": 123, "client_id": "foo", "client_secret": "bar"}`) + return })) defer ts.Close() @@ -78,6 +79,7 @@ func TestRegisterAppWithCancel(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(3 * time.Second) fmt.Fprintln(w, `{"client_id": "foo", "client_secret": "bar"}`) + return })) defer ts.Close() diff --git a/example_test.go b/example_test.go index 32ea5fb..bb72cd9 100644 --- a/example_test.go +++ b/example_test.go @@ -14,7 +14,7 @@ func ExampleRegisterApp() { Server: "https://mstdn.jp", ClientName: "client-name", Scopes: "read write follow", - Website: "https://github.com/mattn/go-mastodon", + Website: "https://github.com/RasmusLindroth/go-mastodon", }) if err != nil { log.Fatal(err) diff --git a/filters_test.go b/filters_test.go index bb7b2fd..71e440d 100644 --- a/filters_test.go +++ b/filters_test.go @@ -322,10 +322,6 @@ func TestDeleteFilter(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } - if r.Method != "DELETE" { - http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) - return - } })) defer ts.Close() diff --git a/lists_test.go b/lists_test.go index b1c9e3b..b6f400e 100644 --- a/lists_test.go +++ b/lists_test.go @@ -15,6 +15,7 @@ func TestGetLists(t *testing.T) { return } fmt.Fprintln(w, `[{"id": "1", "title": "foo"}, {"id": "2", "title": "bar"}]`) + return })) defer ts.Close() @@ -46,6 +47,7 @@ func TestGetAccountLists(t *testing.T) { return } fmt.Fprintln(w, `[{"id": "1", "title": "foo"}, {"id": "2", "title": "bar"}]`) + return })) defer ts.Close() @@ -81,6 +83,7 @@ func TestGetListAccounts(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -116,6 +119,7 @@ func TestGetList(t *testing.T) { return } fmt.Fprintln(w, `{"id": "1", "title": "foo"}`) + return })) defer ts.Close() @@ -125,11 +129,11 @@ func TestGetList(t *testing.T) { ClientSecret: "bar", AccessToken: "zoo", }) - _, err := client.GetList(context.Background(), "2") + list, err := client.GetList(context.Background(), "2") if err == nil { t.Fatalf("should be fail: %v", err) } - list, err := client.GetList(context.Background(), "1") + list, err = client.GetList(context.Background(), "1") if err != nil { t.Fatalf("should not be fail: %v", err) } @@ -145,6 +149,7 @@ func TestCreateList(t *testing.T) { return } fmt.Fprintln(w, `{"id": "1", "title": "foo"}`) + return })) defer ts.Close() @@ -154,11 +159,11 @@ func TestCreateList(t *testing.T) { ClientSecret: "bar", AccessToken: "zoo", }) - _, err := client.CreateList(context.Background(), "") + list, err := client.CreateList(context.Background(), "") if err == nil { t.Fatalf("should be fail: %v", err) } - list, err := client.CreateList(context.Background(), "foo") + list, err = client.CreateList(context.Background(), "foo") if err != nil { t.Fatalf("should not be fail: %v", err) } @@ -178,6 +183,7 @@ func TestRenameList(t *testing.T) { return } fmt.Fprintln(w, `{"id": "1", "title": "bar"}`) + return })) defer ts.Close() @@ -187,11 +193,11 @@ func TestRenameList(t *testing.T) { ClientSecret: "bar", AccessToken: "zoo", }) - _, err := client.RenameList(context.Background(), "2", "bar") + list, err := client.RenameList(context.Background(), "2", "bar") if err == nil { t.Fatalf("should be fail: %v", err) } - list, err := client.RenameList(context.Background(), "1", "bar") + list, err = client.RenameList(context.Background(), "1", "bar") if err != nil { t.Fatalf("should not be fail: %v", err) } @@ -210,6 +216,7 @@ func TestDeleteList(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) return } + return })) defer ts.Close() @@ -239,6 +246,7 @@ func TestAddToList(t *testing.T) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } + return })) defer ts.Close() @@ -264,6 +272,7 @@ func TestRemoveFromList(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) return } + return })) defer ts.Close() diff --git a/mastodon_test.go b/mastodon_test.go index 188b1da..9a8f3e3 100644 --- a/mastodon_test.go +++ b/mastodon_test.go @@ -96,6 +96,7 @@ func TestAuthenticate(t *testing.T) { return } fmt.Fprintln(w, `{"access_token": "zoo"}`) + return })) defer ts.Close() @@ -123,6 +124,7 @@ func TestAuthenticate(t *testing.T) { func TestAuthenticateWithCancel(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(3 * time.Second) + return })) defer ts.Close() @@ -149,6 +151,7 @@ func TestPostStatus(t *testing.T) { return } fmt.Fprintln(w, `{"access_token": "zoo"}`) + return })) defer ts.Close() @@ -181,6 +184,7 @@ func TestPostStatus(t *testing.T) { func TestPostStatusWithCancel(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(3 * time.Second) + return })) defer ts.Close() @@ -315,6 +319,7 @@ func TestPostStatusParams(t *testing.T) { func TestGetTimelineHome(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, `[{"content": "foo"}, {"content": "bar"}]`) + return })) defer ts.Close() @@ -354,6 +359,7 @@ func TestGetTimelineHome(t *testing.T) { func TestGetTimelineHomeWithCancel(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(3 * time.Second) + return })) defer ts.Close() diff --git a/notification_test.go b/notification_test.go index 78cdbdd..28dc975 100644 --- a/notification_test.go +++ b/notification_test.go @@ -28,6 +28,7 @@ func TestGetNotifications(t *testing.T) { return } http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return })) defer ts.Close() @@ -75,6 +76,7 @@ func TestPushSubscription(t *testing.T) { return } http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return })) defer ts.Close() diff --git a/report_test.go b/report_test.go index f25f0b5..db7fadb 100644 --- a/report_test.go +++ b/report_test.go @@ -15,6 +15,7 @@ func TestGetReports(t *testing.T) { return } fmt.Fprintln(w, `[{"id": 122, "action_taken": false}, {"id": 123, "action_taken": true}]`) + return })) defer ts.Close() @@ -54,6 +55,7 @@ func TestReport(t *testing.T) { } else { fmt.Fprintln(w, `{"id": 1234, "action_taken": true}`) } + return })) defer ts.Close() @@ -63,11 +65,11 @@ func TestReport(t *testing.T) { ClientSecret: "bar", AccessToken: "zoo", }) - _, err := client.Report(context.Background(), "121", nil, "") + rp, err := client.Report(context.Background(), "121", nil, "") if err == nil { t.Fatalf("should be fail: %v", err) } - rp, err := client.Report(context.Background(), "122", nil, "") + rp, err = client.Report(context.Background(), "122", nil, "") if err != nil { t.Fatalf("should not be fail: %v", err) } diff --git a/status_test.go b/status_test.go index 6572571..0a5231f 100644 --- a/status_test.go +++ b/status_test.go @@ -12,6 +12,7 @@ import ( func TestGetFavourites(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, `[{"content": "foo"}, {"content": "bar"}]`) + return })) defer ts.Close() @@ -39,6 +40,7 @@ func TestGetFavourites(t *testing.T) { func TestGetBookmarks(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, `[{"content": "foo"}, {"content": "bar"}]`) + return })) defer ts.Close() @@ -70,6 +72,7 @@ func TestGetStatus(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz", "emojis":[{"shortcode":"💩", "url":"http://example.com", "static_url": "http://example.com/static"}]}`) + return })) defer ts.Close() @@ -111,6 +114,7 @@ func TestGetStatusCard(t *testing.T) { return } fmt.Fprintln(w, `{"title": "zzz"}`) + return })) defer ts.Close() @@ -140,6 +144,7 @@ func TestGetStatusContext(t *testing.T) { return } fmt.Fprintln(w, `{"ancestors": [{"content": "zzz"},{"content": "bbb"}]}`) + return })) defer ts.Close() @@ -178,6 +183,7 @@ func TestGetRebloggedBy(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -213,6 +219,7 @@ func TestGetFavouritedBy(t *testing.T) { return } fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) + return })) defer ts.Close() @@ -248,6 +255,7 @@ func TestReblog(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz"}`) + return })) defer ts.Close() @@ -277,6 +285,7 @@ func TestUnreblog(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz"}`) + return })) defer ts.Close() @@ -306,6 +315,7 @@ func TestFavourite(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz"}`) + return })) defer ts.Close() @@ -335,6 +345,7 @@ func TestUnfavourite(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz"}`) + return })) defer ts.Close() @@ -364,6 +375,7 @@ func TestBookmark(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz"}`) + return })) defer ts.Close() @@ -393,6 +405,7 @@ func TestUnbookmark(t *testing.T) { return } fmt.Fprintln(w, `{"content": "zzz"}`) + return })) defer ts.Close() @@ -474,6 +487,7 @@ func TestGetTimelineHashtag(t *testing.T) { return } fmt.Fprintln(w, `[{"content": "zzz"},{"content": "yyy"}]`) + return })) defer ts.Close() @@ -509,6 +523,7 @@ func TestGetTimelineList(t *testing.T) { return } fmt.Fprintln(w, `[{"content": "zzz"},{"content": "yyy"}]`) + return })) defer ts.Close() @@ -544,6 +559,7 @@ func TestGetTimelineMedia(t *testing.T) { return } fmt.Fprintln(w, `[{"content": "zzz"},{"content": "yyy"}]`) + return })) defer ts.Close() @@ -582,6 +598,7 @@ func TestDeleteStatus(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) return } + return })) defer ts.Close() @@ -617,6 +634,7 @@ func TestSearch(t *testing.T) { "statuses":[{"content": "aaa"}], "hashtags":[{"name": "tag"},{"name": "tag2"},{"name": "tag3"}] }`) + return })) defer ts.Close() @@ -661,6 +679,7 @@ func TestUploadMedia(t *testing.T) { return } fmt.Fprintln(w, `{"id": 123}`) + return })) defer ts.Close() @@ -697,6 +716,7 @@ func TestGetConversations(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } fmt.Fprintln(w, `[{"id": "4", "unread":false, "last_status" : {"content": "zzz"}}, {"id": "3", "unread":true, "last_status" : {"content": "bar"}}]`) + return })) defer ts.Close() @@ -734,6 +754,7 @@ func TestDeleteConversation(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) return } + return })) defer ts.Close() @@ -759,6 +780,7 @@ func TestMarkConversationsAsRead(t *testing.T) { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } + return })) defer ts.Close() diff --git a/streaming.go b/streaming.go index 2148ed0..615efec 100644 --- a/streaming.go +++ b/streaming.go @@ -2,8 +2,10 @@ package mastodon import ( "bufio" + "bytes" "context" "encoding/json" + "errors" "io" "net/http" "net/url" @@ -43,10 +45,27 @@ type Event interface { func handleReader(q chan Event, r io.Reader) error { var name string - s := bufio.NewScanner(r) - for s.Scan() { - line := s.Text() - token := strings.SplitN(line, ":", 2) + var lineBuf bytes.Buffer + br := bufio.NewReader(r) + for { + line, isPrefix, err := br.ReadLine() + if err != nil { + if errors.Is(err, io.EOF) { + return nil + } + return err + } + if isPrefix { + lineBuf.Write(line) + continue + } + if lineBuf.Len() > 0 { + lineBuf.Write(line) + line = lineBuf.Bytes() + lineBuf.Reset() + } + + token := strings.SplitN(string(line), ":", 2) if len(token) != 2 { continue } @@ -76,7 +95,6 @@ func handleReader(q chan Event, r io.Reader) error { } } } - return s.Err() } func (c *Client) streaming(ctx context.Context, p string, params url.Values) (chan Event, error) { diff --git a/streaming_test.go b/streaming_test.go index dc03335..fd61f9c 100644 --- a/streaming_test.go +++ b/streaming_test.go @@ -1,6 +1,7 @@ package mastodon import ( + "bufio" "context" "fmt" "net/http" @@ -11,31 +12,40 @@ import ( ) func TestHandleReader(t *testing.T) { + large := "large" + largeContent := strings.Repeat(large, 2*(bufio.MaxScanTokenSize/len(large))) + q := make(chan Event) - r := strings.NewReader(` + r := strings.NewReader(fmt.Sprintf(` event: update data: {content: error} event: update data: {"content": "foo"} +event: update +data: {"content": "%s"} event: notification data: {"type": "mention"} event: delete data: 1234567 :thump - `) - errs := make(chan error, 1) + `, largeContent)) go func() { defer close(q) err := handleReader(q, r) - errs <- err + if err != nil { + t.Fatalf("should not be fail: %v", err) + } }() - var passUpdate, passNotification, passDelete, passError bool + var passUpdate, passUpdateLarge, passNotification, passDelete, passError bool for e := range q { switch event := e.(type) { case *UpdateEvent: - passUpdate = true - if event.Status.Content != "foo" { - t.Fatalf("want %q but %q", "foo", event.Status.Content) + if event.Status.Content == "foo" { + passUpdate = true + } else if event.Status.Content == largeContent { + passUpdateLarge = true + } else { + t.Fatalf("bad update content: %q", event.Status.Content) } case *NotificationEvent: passNotification = true @@ -54,14 +64,10 @@ data: 1234567 } } } - if !passUpdate || !passNotification || !passDelete || !passError { + if !passUpdate || !passUpdateLarge || !passNotification || !passDelete || !passError { t.Fatalf("have not passed through somewhere: "+ - "update %t, notification %t, delete %t, error %t", - passUpdate, passNotification, passDelete, passError) - } - err := <-errs - if err != nil { - t.Fatalf("should not be fail: %v", err) + "update: %t, update (large): %t, notification: %t, delete: %t, error: %t", + passUpdate, passUpdateLarge, passNotification, passDelete, passError) } } @@ -145,6 +151,9 @@ func TestDoStreaming(t *testing.T) { go func() { defer close(q) c.doStreaming(req, q) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } }() var passError bool for e := range q {