Finish LiveThreadService

Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
Vartan Benohanian
2020-09-18 01:20:18 -04:00
parent 58278ffe5d
commit e73b89f0b8
7 changed files with 831 additions and 12 deletions
+176
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"reflect"
@@ -42,6 +43,19 @@ type LiveThread struct {
NSFW bool `json:"nsfw"`
}
// LiveThreadUpdate is an update in a live thread.
type LiveThreadUpdate struct {
ID string `json:"id,omitempty"`
FullID string `json:"name,omitempty"`
Author string `json:"author,omitempty"`
Created *Timestamp `json:"created_utc,omitempty"`
Body string `json:"body,omitempty"`
// todo: add "embeds" field?
Stricken bool `json:"stricken"`
}
// LiveThreadCreateOrUpdateRequest represents a request to create/update a live thread.
type LiveThreadCreateOrUpdateRequest struct {
// No longer than 120 characters.
@@ -133,6 +147,7 @@ type LiveThreadPermissions struct {
Edit bool `permission:"edit"`
Manage bool `permission:"manage"`
Settings bool `permission:"settings"`
// Posting updates to the thread.
Update bool `permission:"update"`
}
@@ -168,6 +183,28 @@ func (p *LiveThreadPermissions) String() (s string) {
return
}
// Now gets information about the currently featured live thread.
// This returns an empty 204 response if no thread is currently featured.
func (s *LiveThreadService) Now(ctx context.Context) (*LiveThread, *Response, error) {
path := "api/live/happening_now"
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 {
if err == io.EOF && resp != nil && resp.StatusCode == http.StatusNoContent {
return nil, resp, nil
}
return nil, resp, err
}
t, _ := root.LiveThread()
return t, resp, nil
}
// 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)
@@ -199,6 +236,94 @@ func (s *LiveThreadService) GetMultiple(ctx context.Context, ids ...string) ([]*
return l.LiveThreads(), resp, nil
}
// Update the live thread by posting an update to it.
// Requires the "update" permission.
func (s *LiveThreadService) Update(ctx context.Context, id, text string) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("body", text)
path := fmt.Sprintf("/api/live/%s/update", id)
req, err := s.client.NewRequest(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Updates gets a list of updates posted in the live thread.
func (s *LiveThreadService) Updates(ctx context.Context, id string, opts *ListOptions) ([]*LiveThreadUpdate, *Response, error) {
path := fmt.Sprintf("live/%s", id)
l, resp, err := s.client.getListing(ctx, path, opts)
if err != nil {
return nil, resp, err
}
return l.LiveThreadUpdates(), resp, nil
}
// UpdateByID gets a specific update in the live thread by its id.
// The ID of the update is the "short" one, i.e. the one that doesn't start with "LiveUpdate_".
func (s *LiveThreadService) UpdateByID(ctx context.Context, threadID, updateID string) (*LiveThreadUpdate, *Response, error) {
path := fmt.Sprintf("live/%s/updates/%s", threadID, updateID)
// this endpoint returns a listing
l, resp, err := s.client.getListing(ctx, path, nil)
if err != nil {
return nil, resp, err
}
var update *LiveThreadUpdate
updates := l.LiveThreadUpdates()
if len(updates) > 0 {
update = updates[0]
}
return update, resp, nil
}
// Discussions gets a list of discussions (posts) about the live thread.
func (s *LiveThreadService) Discussions(ctx context.Context, id string, opts *ListOptions) ([]*Post, *Response, error) {
path := fmt.Sprintf("live/%s/discussions", id)
l, resp, err := s.client.getListing(ctx, path, opts)
if err != nil {
return nil, resp, err
}
return l.Posts(), resp, nil
}
// Strike (mark incorrect and cross out) the content of an update.
// You must either be the author of the update or have the "edit" permission.
func (s *LiveThreadService) Strike(ctx context.Context, threadID, updateID string) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("id", updateID)
path := fmt.Sprintf("api/live/%s/strike_update", threadID)
req, err := s.client.NewRequest(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Delete an update from the live thread.
// You must either be the author of the update or have the "edit" permission.
func (s *LiveThreadService) Delete(ctx context.Context, threadID, updateID string) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("id", updateID)
path := fmt.Sprintf("api/live/%s/delete_update", threadID)
req, err := s.client.NewRequest(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Create a live thread and get its id.
func (s *LiveThreadService) Create(ctx context.Context, request *LiveThreadCreateOrUpdateRequest) (string, *Response, error) {
if request == nil {
@@ -360,6 +485,25 @@ func (s *LiveThreadService) Uninvite(ctx context.Context, threadID, userID strin
// If permissions is nil, all permissions will be granted.
// Requires the "manage" permission.
func (s *LiveThreadService) SetPermissions(ctx context.Context, id, username string, permissions *LiveThreadPermissions) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("name", username)
form.Set("type", "liveupdate_contributor")
form.Set("permissions", permissions.String())
path := fmt.Sprintf("/api/live/%s/set_contributor_permissions", id)
req, err := s.client.NewRequest(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// SetPermissionsForInvite sets the permissions for a contributor who's yet to accept/refuse their invite.
// If permissions is nil, all permissions will be granted.
// Requires the "manage" permission.
func (s *LiveThreadService) SetPermissionsForInvite(ctx context.Context, id, username string, permissions *LiveThreadPermissions) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("name", username)
@@ -391,6 +535,38 @@ func (s *LiveThreadService) Revoke(ctx context.Context, threadID, userID string)
return s.client.Do(ctx, req, nil)
}
// HideDiscussion hides a linked post from the live thread's discussion sidebar.
// The postID should be the base36 ID of the post, i.e. not its full id.
func (s *LiveThreadService) HideDiscussion(ctx context.Context, threadID, postID string) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("link", postID)
path := fmt.Sprintf("/api/live/%s/hide_discussion", threadID)
req, err := s.client.NewRequest(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// UnhideDiscussion unhides a linked post from the live thread's discussion sidebar.
// The postID should be the base36 ID of the post, i.e. not its full id.
func (s *LiveThreadService) UnhideDiscussion(ctx context.Context, threadID, postID string) (*Response, error) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("link", postID)
path := fmt.Sprintf("/api/live/%s/unhide_discussion", threadID)
req, err := s.client.NewRequest(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Report the live thread.
// The reason should be one of:
// spam, vote-manipulation, personal-information, sexualizing-minors, site-breaking
+288 -1
View File
@@ -68,6 +68,89 @@ var expectedLiveThreads = []*LiveThread{
},
}
var expectedLiveThreadUpdates = []*LiveThreadUpdate{
{
ID: "5e46cd94-f968-11ea-9a6a-0e1933241e7d",
FullID: "LiveUpdate_5e46cd94-f968-11ea-9a6a-0e1933241e7d",
Author: "testuser1",
Created: &Timestamp{time.Date(2020, 9, 18, 4, 35, 24, 0, time.UTC)},
Body: "test 2",
Stricken: true,
},
{
ID: "fc44f204-f964-11ea-b148-0e2e56a0425f",
FullID: "LiveUpdate_fc44f204-f964-11ea-b148-0e2e56a0425f",
Author: "testuser1",
Created: &Timestamp{time.Date(2020, 9, 18, 4, 11, 11, 0, time.UTC)},
Body: "test 1",
Stricken: true,
},
}
var expectedLiveThreadUpdate = &LiveThreadUpdate{
ID: "fc44f204-f964-11ea-b148-0e2e56a0425f",
FullID: "LiveUpdate_fc44f204-f964-11ea-b148-0e2e56a0425f",
Author: "testuser1",
Created: &Timestamp{time.Date(2020, 9, 18, 4, 11, 11, 0, time.UTC)},
Body: "test 1",
Stricken: true,
}
var expectedLiveThreadDiscussions = []*Post{
{
ID: "test1",
FullID: "t3_test1",
Created: &Timestamp{time.Date(2020, 9, 16, 12, 37, 31, 0, time.UTC)},
Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
Permalink: "/r/live/comments/test1/test_title/",
URL: "https://www.reddit.com/live/15nfp4mtfbo14/",
Title: "test title",
Score: 22,
UpvoteRatio: 0.9,
NumberOfComments: 1,
SubredditName: "live",
SubredditNamePrefixed: "r/live",
SubredditID: "t5_32o7w",
SubredditSubscribers: 24501,
Author: "TestUser",
AuthorID: "t2_test1",
},
{
ID: "test2",
FullID: "t3_test2",
Created: &Timestamp{time.Date(2020, 9, 16, 12, 37, 1, 0, time.UTC)},
Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
Permalink: "/r/live/comments/test2/test_title/",
URL: "https://www.reddit.com/live/15nfp4mtfbo14/",
Title: "test title",
Score: 71,
UpvoteRatio: 0.97,
NumberOfComments: 34,
SubredditName: "live",
SubredditNamePrefixed: "r/live",
SubredditID: "t5_32o7w",
SubredditSubscribers: 24501,
Author: "TestUser",
AuthorID: "t2_test1",
},
}
var expectedLiveThreadContributors = &LiveThreadContributors{
Current: []*LiveThreadContributor{
{ID: "t2_test1", Name: "test1", Permissions: []string{"all"}},
@@ -103,6 +186,37 @@ func TestLiveThreadService_Get(t *testing.T) {
require.Equal(t, expectedLiveThread, liveThread)
}
func TestLiveThreadService_Now(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
blob, err := readFileContents("../testdata/live-thread/live-thread.json")
require.NoError(t, err)
mux.HandleFunc("/api/live/happening_now", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, blob)
})
liveThread, _, err := client.LiveThread.Now(ctx)
require.NoError(t, err)
require.Equal(t, expectedLiveThread, liveThread)
}
func TestLiveThreadService_Now_NoContent(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/happening_now", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
w.WriteHeader(204)
})
liveThread, _, err := client.LiveThread.Now(ctx)
require.NoError(t, err)
require.Nil(t, liveThread)
}
func TestLiveThreadService_GetMultiple(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
@@ -123,6 +237,117 @@ func TestLiveThreadService_GetMultiple(t *testing.T) {
require.Equal(t, expectedLiveThreads, liveThreads)
}
func TestLiveThreadService_Update(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/id123/update", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
form := url.Values{}
form.Set("api_type", "json")
form.Set("body", "test")
err := r.ParseForm()
require.NoError(t, err)
require.Equal(t, form, r.PostForm)
})
_, err := client.LiveThread.Update(ctx, "id123", "test")
require.NoError(t, err)
}
func TestLiveThreadService_Updates(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
blob, err := readFileContents("../testdata/live-thread/updates.json")
require.NoError(t, err)
mux.HandleFunc("/live/id123", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, blob)
})
liveThreadUpdates, _, err := client.LiveThread.Updates(ctx, "id123", nil)
require.NoError(t, err)
require.Equal(t, expectedLiveThreadUpdates, liveThreadUpdates)
}
func TestLiveThreadService_UpdateByID(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
blob, err := readFileContents("../testdata/live-thread/update.json")
require.NoError(t, err)
mux.HandleFunc("/live/id123/updates/update123", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, blob)
})
liveThreadUpdate, _, err := client.LiveThread.UpdateByID(ctx, "id123", "update123")
require.NoError(t, err)
require.Equal(t, expectedLiveThreadUpdate, liveThreadUpdate)
}
func TestLiveThreadService_Discussions(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
blob, err := readFileContents("../testdata/live-thread/discussions.json")
require.NoError(t, err)
mux.HandleFunc("/live/id123/discussions", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, blob)
})
liveThreadDiscussions, _, err := client.LiveThread.Discussions(ctx, "id123", nil)
require.NoError(t, err)
require.Equal(t, expectedLiveThreadDiscussions, liveThreadDiscussions)
}
func TestLiveThreadService_Strike(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/id123/strike_update", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
form := url.Values{}
form.Set("api_type", "json")
form.Set("id", "update123")
err := r.ParseForm()
require.NoError(t, err)
require.Equal(t, form, r.PostForm)
})
_, err := client.LiveThread.Strike(ctx, "id123", "update123")
require.NoError(t, err)
}
func TestLiveThreadService_Delete(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/id123/delete_update", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
form := url.Values{}
form.Set("api_type", "json")
form.Set("id", "update123")
err := r.ParseForm()
require.NoError(t, err)
require.Equal(t, form, r.PostForm)
})
_, err := client.LiveThread.Delete(ctx, "id123", "update123")
require.NoError(t, err)
}
func TestLiveThreadService_Create(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
@@ -369,7 +594,7 @@ func TestLiveThreadService_SetPermissions(t *testing.T) {
form := url.Values{}
form.Set("api_type", "json")
form.Set("name", "testuser")
form.Set("type", "liveupdate_contributor_invite")
form.Set("type", "liveupdate_contributor")
form.Set("permissions", "-all,-close,+discussions,+edit,-manage,+settings,-update")
err := r.ParseForm()
@@ -381,6 +606,28 @@ func TestLiveThreadService_SetPermissions(t *testing.T) {
require.NoError(t, err)
}
func TestLiveThreadService_SetPermissionsForInvite(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/id123/set_contributor_permissions", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
form := url.Values{}
form.Set("api_type", "json")
form.Set("name", "testuser")
form.Set("type", "liveupdate_contributor_invite")
form.Set("permissions", "-all,-close,+discussions,+edit,-manage,+settings,-update")
err := r.ParseForm()
require.NoError(t, err)
require.Equal(t, form, r.PostForm)
})
_, err := client.LiveThread.SetPermissionsForInvite(ctx, "id123", "testuser", &LiveThreadPermissions{Discussions: true, Edit: true, Settings: true})
require.NoError(t, err)
}
func TestLiveThreadService_Revoke(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
@@ -401,6 +648,46 @@ func TestLiveThreadService_Revoke(t *testing.T) {
require.NoError(t, err)
}
func TestLiveThreadService_HideDiscussion(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/id123/hide_discussion", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
form := url.Values{}
form.Set("api_type", "json")
form.Set("link", "t3_test")
err := r.ParseForm()
require.NoError(t, err)
require.Equal(t, form, r.PostForm)
})
_, err := client.LiveThread.HideDiscussion(ctx, "id123", "t3_test")
require.NoError(t, err)
}
func TestLiveThreadService_UnhideDiscussion(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
mux.HandleFunc("/api/live/id123/unhide_discussion", func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
form := url.Values{}
form.Set("api_type", "json")
form.Set("link", "t3_test")
err := r.ParseForm()
require.NoError(t, err)
require.Equal(t, form, r.PostForm)
})
_, err := client.LiveThread.UnhideDiscussion(ctx, "id123", "t3_test")
require.NoError(t, err)
}
func TestLiveThreadService_Report(t *testing.T) {
client, mux, teardown := setup()
defer teardown()
+2 -2
View File
@@ -322,12 +322,12 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res
if w, ok := v.(io.Writer); ok {
_, err = io.Copy(w, response.Body)
if err != nil {
return nil, err
return response, err
}
} else {
err = json.NewDecoder(response.Body).Decode(v)
if err != nil {
return nil, err
return response, err
}
}
+18
View File
@@ -18,6 +18,7 @@ const (
kindUserList = "UserList"
kindMore = "more"
kindLiveThread = "LiveUpdateEvent"
kindLiveThreadUpdate = "LiveUpdate"
kindModAction = "modaction"
kindMulti = "LabeledMulti"
kindMultiDescription = "LabeledMultiDescription"
@@ -92,6 +93,8 @@ func (t *thing) UnmarshalJSON(b []byte) error {
v = new(Subreddit)
case kindLiveThread:
v = new(LiveThread)
case kindLiveThreadUpdate:
v = new(LiveThreadUpdate)
case kindModAction:
v = new(ModAction)
case kindMulti:
@@ -160,6 +163,11 @@ func (t *thing) LiveThread() (v *LiveThread, ok bool) {
return
}
func (t *thing) LiveThreadUpdate() (v *LiveThreadUpdate, ok bool) {
v, ok = t.Data.(*LiveThreadUpdate)
return
}
func (t *thing) ModAction() (v *ModAction, ok bool) {
v, ok = t.Data.(*ModAction)
return
@@ -314,6 +322,13 @@ func (l *listing) LiveThreads() []*LiveThread {
return l.things.LiveThreads
}
func (l *listing) LiveThreadUpdates() []*LiveThreadUpdate {
if l == nil {
return nil
}
return l.things.LiveThreadUpdates
}
type things struct {
Comments []*Comment
Mores []*More
@@ -323,6 +338,7 @@ type things struct {
ModActions []*ModAction
Multis []*Multi
LiveThreads []*LiveThread
LiveThreadUpdates []*LiveThreadUpdate
}
// UnmarshalJSON implements the json.Unmarshaler interface.
@@ -355,6 +371,8 @@ func (t *things) add(things ...thing) {
t.Multis = append(t.Multis, v)
case *LiveThread:
t.LiveThreads = append(t.LiveThreads, v)
case *LiveThreadUpdate:
t.LiveThreadUpdates = append(t.LiveThreadUpdates, v)
}
}
}
+271
View File
@@ -0,0 +1,271 @@
{
"kind": "Listing",
"data": {
"modhash": null,
"dist": 2,
"children": [
{
"kind": "t3",
"data": {
"approved_at_utc": null,
"subreddit": "live",
"selftext": "",
"author_fullname": "t2_test1",
"saved": false,
"mod_reason_title": null,
"gilded": 0,
"clicked": false,
"title": "test title",
"link_flair_richtext": [],
"subreddit_name_prefixed": "r/live",
"hidden": false,
"pwls": 6,
"link_flair_css_class": null,
"downs": 0,
"thumbnail_height": 140,
"top_awarded_type": null,
"hide_score": false,
"name": "t3_test1",
"quarantine": false,
"link_flair_text_color": "dark",
"upvote_ratio": 0.9,
"author_flair_background_color": null,
"subreddit_type": "public",
"ups": 22,
"total_awards_received": 0,
"media_embed": {
"content": "\n&lt;div class=\"psuedo-selftext\"&gt;\n &lt;iframe src=\"//www.redditmedia.com/live/15nfp4mtfbo14/embed\" height=\"500\"&gt;&lt;/iframe&gt;\n&lt;/div&gt;\n",
"width": 710,
"scrolling": false,
"height": 500
},
"thumbnail_width": 140,
"author_flair_template_id": null,
"is_original_content": false,
"user_reports": [],
"secure_media": {
"event_id": "15nfp4mtfbo14",
"type": "liveupdate"
},
"is_reddit_media_domain": false,
"is_meta": false,
"category": null,
"secure_media_embed": {
"content": "\n&lt;div class=\"psuedo-selftext\"&gt;\n &lt;iframe src=\"//www.redditmedia.com/live/15nfp4mtfbo14/embed\" height=\"500\"&gt;&lt;/iframe&gt;\n&lt;/div&gt;\n",
"width": 710,
"scrolling": false,
"media_domain_url": "https://www.redditmedia.com/mediaembed/test1",
"height": 500
},
"link_flair_text": "LIVE THREAD",
"can_mod_post": false,
"score": 22,
"approved_by": null,
"author_premium": true,
"thumbnail": "default",
"edited": false,
"author_flair_css_class": null,
"author_flair_richtext": [],
"gildings": {},
"content_categories": null,
"is_self": false,
"mod_note": null,
"created": 1600288651.0,
"link_flair_type": "text",
"wls": 6,
"removed_by_category": null,
"banned_by": null,
"author_flair_type": "text",
"domain": "reddit.com",
"allow_live_comments": false,
"selftext_html": null,
"likes": null,
"suggested_sort": null,
"banned_at_utc": null,
"url_overridden_by_dest": "https://www.reddit.com/live/15nfp4mtfbo14/",
"view_count": null,
"archived": false,
"no_follow": false,
"is_crosspostable": true,
"pinned": false,
"over_18": false,
"all_awardings": [],
"awarders": [],
"media_only": false,
"can_gild": true,
"spoiler": false,
"locked": false,
"author_flair_text": null,
"treatment_tags": [],
"visited": false,
"removed_by": null,
"num_reports": null,
"distinguished": null,
"subreddit_id": "t5_32o7w",
"mod_reason_by": null,
"removal_reason": null,
"link_flair_background_color": "",
"id": "test1",
"is_robot_indexable": true,
"report_reasons": null,
"author": "TestUser",
"discussion_type": null,
"num_comments": 1,
"send_replies": true,
"whitelist_status": "all_ads",
"contest_mode": false,
"mod_reports": [],
"author_patreon_flair": false,
"author_flair_text_color": null,
"permalink": "/r/live/comments/test1/test_title/",
"parent_whitelist_status": "all_ads",
"stickied": false,
"url": "https://www.reddit.com/live/15nfp4mtfbo14/",
"subreddit_subscribers": 24501,
"created_utc": 1600259851.0,
"num_crossposts": 0,
"media": {
"event_id": "15nfp4mtfbo14",
"type": "liveupdate"
},
"is_video": false
}
},
{
"kind": "t3",
"data": {
"approved_at_utc": null,
"subreddit": "live",
"selftext": "",
"author_fullname": "t2_test1",
"saved": false,
"mod_reason_title": null,
"gilded": 0,
"clicked": false,
"title": "test title",
"link_flair_richtext": [
{
"e": "text",
"t": "LIVE THREAD CLOSED | No further updates."
}
],
"subreddit_name_prefixed": "r/live",
"hidden": false,
"pwls": 6,
"link_flair_css_class": "diss",
"downs": 0,
"thumbnail_height": 140,
"top_awarded_type": null,
"hide_score": false,
"name": "t3_test2",
"quarantine": false,
"link_flair_text_color": "dark",
"upvote_ratio": 0.97,
"author_flair_background_color": null,
"subreddit_type": "public",
"ups": 71,
"total_awards_received": 0,
"media_embed": {
"content": "\n&lt;div class=\"psuedo-selftext\"&gt;\n &lt;iframe src=\"//www.redditmedia.com/live/15nfp4mtfbo14/embed\" height=\"500\"&gt;&lt;/iframe&gt;\n&lt;/div&gt;\n",
"width": 710,
"scrolling": false,
"height": 500
},
"thumbnail_width": 140,
"author_flair_template_id": null,
"is_original_content": false,
"user_reports": [],
"secure_media": {
"event_id": "15nfp4mtfbo14",
"type": "liveupdate"
},
"is_reddit_media_domain": false,
"is_meta": false,
"category": null,
"secure_media_embed": {
"content": "\n&lt;div class=\"psuedo-selftext\"&gt;\n &lt;iframe src=\"//www.redditmedia.com/live/15nfp4mtfbo14/embed\" height=\"500\"&gt;&lt;/iframe&gt;\n&lt;/div&gt;\n",
"width": 710,
"scrolling": false,
"media_domain_url": "https://www.redditmedia.com/mediaembed/itulo6",
"height": 500
},
"link_flair_text": "LIVE THREAD CLOSED | No further updates.",
"can_mod_post": false,
"score": 71,
"approved_by": null,
"author_premium": true,
"thumbnail": "https://b.thumbs.redditmedia.com/rZKNaYfha47BqSqVTn2S7WGm5-ydloMOqz3Oqli87aU.jpg",
"edited": false,
"author_flair_css_class": null,
"author_flair_richtext": [],
"gildings": {},
"content_categories": null,
"is_self": false,
"mod_note": null,
"created": 1600288621.0,
"link_flair_type": "richtext",
"wls": 6,
"removed_by_category": null,
"banned_by": null,
"author_flair_type": "text",
"domain": "reddit.com",
"allow_live_comments": true,
"selftext_html": null,
"likes": null,
"suggested_sort": "new",
"banned_at_utc": null,
"url_overridden_by_dest": "https://www.reddit.com/live/15nfp4mtfbo14/",
"view_count": null,
"archived": false,
"no_follow": false,
"is_crosspostable": true,
"pinned": false,
"over_18": false,
"all_awardings": [],
"awarders": [],
"media_only": false,
"link_flair_template_id": "9b12fc60-ff01-11e3-b179-12313b0a9e38",
"can_gild": true,
"spoiler": false,
"locked": false,
"author_flair_text": null,
"treatment_tags": [],
"visited": false,
"removed_by": null,
"num_reports": null,
"distinguished": null,
"subreddit_id": "t5_32o7w",
"mod_reason_by": null,
"removal_reason": null,
"link_flair_background_color": "#f5f5f5",
"id": "test2",
"is_robot_indexable": true,
"report_reasons": null,
"author": "TestUser",
"discussion_type": null,
"num_comments": 34,
"send_replies": true,
"whitelist_status": "all_ads",
"contest_mode": false,
"mod_reports": [],
"author_patreon_flair": false,
"author_flair_text_color": null,
"permalink": "/r/live/comments/test2/test_title/",
"parent_whitelist_status": "all_ads",
"stickied": false,
"url": "https://www.reddit.com/live/15nfp4mtfbo14/",
"subreddit_subscribers": 24501,
"created_utc": 1600259821.0,
"num_crossposts": 0,
"media": {
"event_id": "15nfp4mtfbo14",
"type": "liveupdate"
},
"is_video": false
}
}
],
"after": null,
"before": null
}
}
+26
View File
@@ -0,0 +1,26 @@
{
"kind": "Listing",
"data": {
"modhash": null,
"dist": null,
"children": [
{
"kind": "LiveUpdate",
"data": {
"body": "test 1",
"name": "LiveUpdate_fc44f204-f964-11ea-b148-0e2e56a0425f",
"mobile_embeds": [],
"author": "testuser1",
"embeds": [],
"created": 1600431071.0,
"created_utc": 1600402271.0,
"body_html": "&lt;div class=\"md\"&gt;&lt;p&gt;test 1&lt;/p&gt;\n&lt;/div&gt;",
"stricken": true,
"id": "fc44f204-f964-11ea-b148-0e2e56a0425f"
}
}
],
"after": null,
"before": null
}
}
+41
View File
@@ -0,0 +1,41 @@
{
"kind": "Listing",
"data": {
"modhash": null,
"dist": null,
"children": [
{
"kind": "LiveUpdate",
"data": {
"body": "test 2",
"name": "LiveUpdate_5e46cd94-f968-11ea-9a6a-0e1933241e7d",
"mobile_embeds": [],
"author": "testuser1",
"embeds": [],
"created": 1600432524.0,
"created_utc": 1600403724.0,
"body_html": "&lt;div class=\"md\"&gt;&lt;p&gt;test 2&lt;/p&gt;\n&lt;/div&gt;",
"stricken": true,
"id": "5e46cd94-f968-11ea-9a6a-0e1933241e7d"
}
},
{
"kind": "LiveUpdate",
"data": {
"body": "test 1",
"name": "LiveUpdate_fc44f204-f964-11ea-b148-0e2e56a0425f",
"mobile_embeds": [],
"author": "testuser1",
"embeds": [],
"created": 1600431071.0,
"created_utc": 1600402271.0,
"body_html": "&lt;div class=\"md\"&gt;&lt;p&gt;test 1&lt;/p&gt;\n&lt;/div&gt;",
"stricken": true,
"id": "fc44f204-f964-11ea-b148-0e2e56a0425f"
}
}
],
"after": null,
"before": null
}
}