From 359f8126a179095148ce106cf499175abd852cdf Mon Sep 17 00:00:00 2001 From: Vartan Benohanian Date: Tue, 15 Sep 2020 21:41:12 -0400 Subject: [PATCH] Create LiveThreadService Signed-off-by: Vartan Benohanian --- reddit/live-thread.go | 54 +++++++++++++++++++++++++++ reddit/live-thread_test.go | 46 +++++++++++++++++++++++ reddit/reddit.go | 2 + reddit/reddit_test.go | 1 + reddit/things.go | 8 ++++ testdata/live-thread/live-thread.json | 25 +++++++++++++ 6 files changed, 136 insertions(+) create mode 100644 reddit/live-thread.go create mode 100644 reddit/live-thread_test.go create mode 100644 testdata/live-thread/live-thread.json diff --git a/reddit/live-thread.go b/reddit/live-thread.go new file mode 100644 index 0000000..50235c1 --- /dev/null +++ b/reddit/live-thread.go @@ -0,0 +1,54 @@ +package reddit + +import ( + "context" + "fmt" + "net/http" +) + +// LiveThreadService handles communication with the live thread +// related methods of the Reddit API. +// +// Reddit API docs: https://www.reddit.com/dev/api/#section_live +type LiveThreadService struct { + client *Client +} + +// LiveThread is a thread on Reddit that provides real-time updates. +type LiveThread struct { + ID string `json:"id,omitempty"` + FullID string `json:"name,omitempty"` + Created *Timestamp `json:"created_utc,omitempty"` + + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Resources string `json:"resources,omitempty"` + + State string `json:"state,omitempty"` + ViewerCount int `json:"viewer_count"` + ViewerCountFuzzed bool `json:"viewer_count_fuzzed"` + + WebSocketURL string `json:"websocket_url,omitempty"` + + Announcement bool `json:"is_announcement"` + NSFW bool `json:"nsfw"` +} + +// Get information about a live thread. +func (s *LiveThreadService) Get(ctx context.Context, id string) (*LiveThread, *Response, error) { + path := fmt.Sprintf("live/%s/about", id) + + req, err := s.client.NewRequest(http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(thing) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + t, _ := root.LiveThread() + return t, resp, nil +} diff --git a/reddit/live-thread_test.go b/reddit/live-thread_test.go new file mode 100644 index 0000000..658c43a --- /dev/null +++ b/reddit/live-thread_test.go @@ -0,0 +1,46 @@ +package reddit + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +var expectedLiveThread = &LiveThread{ + ID: "15nevtv8e54dh", + FullID: "LiveUpdateEvent_15nevtv8e54dh", + Created: &Timestamp{time.Date(2020, 9, 16, 1, 20, 27, 0, time.UTC)}, + + Title: "test", + Description: "test", + Resources: "", + + State: "live", + ViewerCount: 6, + ViewerCountFuzzed: true, + + WebSocketURL: "wss://ws-078adc7cb2099a9df.wss.redditmedia.com/live/15nevtv8e54dh?m=AQAA7rxiX6EpLYFCFZ0KJD4lVAPaMt0A1z2-xJ1b2dWCmxNIfMwL", + + Announcement: false, + NSFW: false, +} + +func TestLiveThreadService_Get(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + blob, err := readFileContents("../testdata/live-thread/live-thread.json") + require.NoError(t, err) + + mux.HandleFunc("/live/id123/about", func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, http.MethodGet, r.Method) + fmt.Fprint(w, blob) + }) + + liveThread, _, err := client.LiveThread.Get(ctx, "id123") + require.NoError(t, err) + require.Equal(t, expectedLiveThread, liveThread) +} diff --git a/reddit/reddit.go b/reddit/reddit.go index a362cae..19ac2c6 100644 --- a/reddit/reddit.go +++ b/reddit/reddit.go @@ -71,6 +71,7 @@ type Client struct { Flair *FlairService Gold *GoldService Listings *ListingsService + LiveThread *LiveThreadService Message *MessageService Moderation *ModerationService Multi *MultiService @@ -102,6 +103,7 @@ func newClient() *Client { client.Flair = &FlairService{client: client} client.Gold = &GoldService{client: client} client.Listings = &ListingsService{client: client} + client.LiveThread = &LiveThreadService{client: client} client.Message = &MessageService{client: client} client.Moderation = &ModerationService{client: client} client.Multi = &MultiService{client: client} diff --git a/reddit/reddit_test.go b/reddit/reddit_test.go index 13db3db..b7654d5 100644 --- a/reddit/reddit_test.go +++ b/reddit/reddit_test.go @@ -64,6 +64,7 @@ func testClientServices(t *testing.T, c *Client) { "Flair", "Gold", "Listings", + "LiveThread", "Message", "Moderation", "Multi", diff --git a/reddit/things.go b/reddit/things.go index b5b6977..4ac7995 100644 --- a/reddit/things.go +++ b/reddit/things.go @@ -17,6 +17,7 @@ const ( kindTrophyList = "TrophyList" kindUserList = "UserList" kindMore = "more" + kindLiveThread = "LiveUpdateEvent" kindModAction = "modaction" kindMulti = "LabeledMulti" kindMultiDescription = "LabeledMultiDescription" @@ -89,6 +90,8 @@ func (t *thing) UnmarshalJSON(b []byte) error { v = new(Post) case kindSubreddit: v = new(Subreddit) + case kindLiveThread: + v = new(LiveThread) case kindModAction: v = new(ModAction) case kindMulti: @@ -152,6 +155,11 @@ func (t *thing) Subreddit() (v *Subreddit, ok bool) { return } +func (t *thing) LiveThread() (v *LiveThread, ok bool) { + v, ok = t.Data.(*LiveThread) + return +} + func (t *thing) ModAction() (v *ModAction, ok bool) { v, ok = t.Data.(*ModAction) return diff --git a/testdata/live-thread/live-thread.json b/testdata/live-thread/live-thread.json new file mode 100644 index 0000000..8ed65e0 --- /dev/null +++ b/testdata/live-thread/live-thread.json @@ -0,0 +1,25 @@ +{ + "kind": "LiveUpdateEvent", + "data": { + "total_views": null, + "description": "test", + "description_html": "<div class=\"md\"><p>test</p>\n</div>", + "created": 1600248027.0, + "title": "test", + "created_utc": 1600219227.0, + "button_cta": "", + "websocket_url": "wss://ws-078adc7cb2099a9df.wss.redditmedia.com/live/15nevtv8e54dh?m=AQAA7rxiX6EpLYFCFZ0KJD4lVAPaMt0A1z2-xJ1b2dWCmxNIfMwL", + "name": "LiveUpdateEvent_15nevtv8e54dh", + "is_announcement": false, + "state": "live", + "announcement_url": "", + "nsfw": false, + "viewer_count": 6, + "num_times_dismissable": 1, + "viewer_count_fuzzed": true, + "resources_html": "", + "id": "15nevtv8e54dh", + "resources": "", + "icon": "" + } +}