From fd6533a50809b3aeb5b138ced6cf5aa8769e33d9 Mon Sep 17 00:00:00 2001 From: hiromi-mi Date: Tue, 25 Feb 2020 07:05:13 +0900 Subject: [PATCH] Support conversations API Support these APIs added in Mastodon 2.6.0. - GET /api/v1/conversations - DELETE /api/v1/conversations/:id - POST /api/v1/conversations/:id/read --- README.md | 3 ++ status.go | 30 ++++++++++++++++++ status_test.go | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/README.md b/README.md index b6639a8..b74f788 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,9 @@ func main() { * [x] GET /api/v1/accounts/search * [x] POST /api/v1/apps * [x] GET /api/v1/blocks +* [x] GET /api/v1/conversations +* [x] DELETE /api/v1/conversations/:id +* [x] POST /api/v1/conversations/:id/read * [x] GET /api/v1/favourites * [x] GET /api/v1/follow_requests * [x] POST /api/v1/follow_requests/:id/authorize diff --git a/status.go b/status.go index 7bee52a..ebf7a9f 100644 --- a/status.go +++ b/status.go @@ -61,6 +61,14 @@ type Card struct { Height int64 `json:"height"` } +// Conversation hold information for mastodon conversation. +type Conversation struct { + ID ID `json:"id"` + Accounts []*Account `json:"accounts"` + Unread bool `json:"unread"` + LastStatus *Status `json:"last_status"` +} + // GetFavourites return the favorite list of the current user. func (c *Client) GetFavourites(ctx context.Context, pg *Pagination) ([]*Status, error) { var statuses []*Status @@ -307,3 +315,25 @@ func (c *Client) GetTimelineDirect(ctx context.Context, pg *Pagination) ([]*Stat } return statuses, nil } + +// GetConversations return direct conversations. +func (c *Client) GetConversations(ctx context.Context, pg *Pagination) ([]*Conversation, error) { + params := url.Values{} + + var conversations []*Conversation + err := c.doAPI(ctx, http.MethodGet, "/api/v1/conversations", params, &conversations, pg) + if err != nil { + return nil, err + } + return conversations, nil +} + +// DeleteConversation delete the conversation specified by id. +func (c *Client) DeleteConversation(ctx context.Context, id ID) error { + return c.doAPI(ctx, http.MethodDelete, fmt.Sprintf("/api/v1/conversations/%s", id), nil, nil, nil) +} + +// MarkConversationAsRead mark the conversation as read. +func (c *Client) MarkConversationAsRead(ctx context.Context, id ID) error { + return c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/conversations/%s/read", id), nil, nil, nil) +} diff --git a/status_test.go b/status_test.go index 7536ffb..85c0967 100644 --- a/status_test.go +++ b/status_test.go @@ -621,3 +621,89 @@ func TestUploadMedia(t *testing.T) { t.Fatalf("want %q but %q", "123", attachment.ID) } } + +func TestGetConversations(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/conversations" { + 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() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + convs, err := client.GetConversations(context.Background(), nil) + if err != nil { + t.Fatalf("should not be fail: %v", err) + } + if len(convs) != 2 { + t.Fatalf("result should be 2: %d", len(convs)) + } + if convs[0].ID != "4" { + t.Fatalf("want %q but %q", "4", convs[0].ID) + } + if convs[0].LastStatus.Content != "zzz" { + t.Fatalf("want %q but %q", "zzz", convs[0].LastStatus.Content) + } + if convs[1].Unread != true { + t.Fatalf("unread should be true: %t", convs[1].Unread) + } +} + +func TestDeleteConversation(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/conversations/12345678" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + if r.Method != "DELETE" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) + return + } + return + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "hoge", + }) + err = client.DeleteConversation(context.Background(), "12345678") + if err != nil { + t.Fatalf("should not be fail: %v", err) + } +} + +func TestMarkConversationsAsRead(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/api/v1/conversations/111111/read" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + if r.Method != "POST" { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + return + })) + defer ts.Close() + + client := NewClient(&Config{ + Server: ts.URL, + ClientID: "foo", + ClientSecret: "bar", + AccessToken: "zoo", + }) + err := client.MarkConversationAsRead(context.Background(), "111111") + if err != nil { + t.Fatalf("should not be fail: %v", err) + } +}