diff --git a/reddit/subreddit.go b/reddit/subreddit.go index 316a9d6..d6bd451 100644 --- a/reddit/subreddit.go +++ b/reddit/subreddit.go @@ -256,6 +256,51 @@ type SubredditSettings struct { WikiMinimumKarma *int `url:"wiki_edit_karma,omitempty" json:"wiki_edit_karma,omitempty"` } +// SubredditPostRequirements is a list of moderator-designed requirements to post to a subreddit. +type SubredditPostRequirements struct { + // Sentence or two on how to successfully post to the subreddit. + Guidelines string `json:"guidelines_text"` + GuidelinesDisplayPolicy string `json:"guidelines_display_policy"` + + TitleMinLength int `json:"title_text_min_length"` + TitleMaxLength int `json:"title_text_max_length"` + + BodyMinLength int `json:"body_text_min_length"` + BodyMaxLength int `json:"body_text_max_length"` + + // Do not allow any of these words in the title. + TitleBlacklistedStrings []string `json:"title_blacklisted_strings"` + // Do not allow any of these words in the body. + BodyBlacklistedStrings []string `json:"body_blacklisted_strings"` + + // Require at least one of these words in the title. + TitleRequiredStrings []string `json:"title_required_strings"` + // Require at least one of these words in the body. + BodyRequiredStrings []string `json:"body_required_strings"` + + // Block link posts with these domains. + DomainBlacklist []string `json:"domain_blacklist"` + // Only allow link posts with these domains. + DomainWhitelist []string `json:"domain_whitelist"` + + // One of: required, notAllowed, none. + // Meaning that a selftext post's body is required, not allowed, or optional, respectively. + BodyRestrictionPolicy string `json:"body_restriction_policy"` + LinkRestrictionPolicy string `json:"link_restriction_policy"` + + GalleryMinItems int `json:"gallery_min_items"` + GalleryMaxItems int `json:"gallery_max_items"` + GalleryCaptionsRequirement string `json:"gallery_captions_requirement"` + GalleryURLsRequirement string `json:"gallery_urls_requirement"` + + // Prevent users from posting a link that was already posted to your community within x days of the original. + LinkRepostAge int `json:"link_repost_age"` + FlairRequired bool `json:"is_flair_required"` + + TitleRegexes []string `json:"title_regexes"` + BodyRegexes []string `json:"body_regexes"` +} + func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts interface{}) ([]*Post, *Response, error) { path := sort if subreddit != "" { @@ -1099,7 +1144,8 @@ func (s *SubredditService) Create(ctx context.Context, name string, request *Sub // Edit a subreddit. // This endpoint expects all values of the request to be provided. -// To make this easier, it might be useful to get the subreddit's current settings via GetSettings(), and use that as a starting point. +// To make this easier, it might be useful to get the subreddit's current settings via GetSettings(), +// and use that as a starting point. It even returns the subreddit's ID, which is needed for this. func (s *SubredditService) Edit(ctx context.Context, subredditID string, request *SubredditSettings) (*Response, error) { if request == nil { return nil, errors.New("*SubredditSettings: cannot be nil") @@ -1131,3 +1177,21 @@ func (s *SubredditService) GetSettings(ctx context.Context, subreddit string) (* settings, _ := t.SubredditSettings() return settings, resp, nil } + +// PostRequirements returns the subreddit's moderator-designed requirements to post to it. +// Clients may use the values returned by this method to pre-validate submissions to the subreddit. +func (s *SubredditService) PostRequirements(ctx context.Context, subreddit string) (*SubredditPostRequirements, *Response, error) { + path := fmt.Sprintf("api/v1/%s/post_requirements", subreddit) + req, err := s.client.NewRequest(http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(SubredditPostRequirements) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root, resp, nil +} diff --git a/reddit/subreddit_test.go b/reddit/subreddit_test.go index d405680..dab0ad8 100644 --- a/reddit/subreddit_test.go +++ b/reddit/subreddit_test.go @@ -400,6 +400,40 @@ var expectedSubredditSettings = &SubredditSettings{ WikiMinimumKarma: Int(0), } +var expectedSubredditPostRequirements = &SubredditPostRequirements{ + Guidelines: "test", + GuidelinesDisplayPolicy: "", + + TitleMinLength: 50, + TitleMaxLength: 200, + + BodyMinLength: 50, + BodyMaxLength: 2000, + + TitleBlacklistedStrings: []string{"no"}, + BodyBlacklistedStrings: []string{"no"}, + + TitleRequiredStrings: []string{"yes"}, + BodyRequiredStrings: []string{"yes"}, + + DomainBlacklist: []string{"example.com"}, + DomainWhitelist: []string{}, + + BodyRestrictionPolicy: "none", + LinkRestrictionPolicy: "none", + + GalleryMinItems: 2, + GalleryMaxItems: 20, + GalleryCaptionsRequirement: "none", + GalleryURLsRequirement: "none", + + LinkRepostAge: 2, + FlairRequired: false, + + TitleRegexes: []string{}, + BodyRegexes: []string{}, +} + func TestSubredditService_HotPosts(t *testing.T) { client, mux, teardown := setup() defer teardown() @@ -1586,6 +1620,128 @@ func TestSubredditService_UploadImage_Error(t *testing.T) { require.EqualError(t, err, "could not upload image: error one; error two") } +func TestSubredditService_Create(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc("/api/site_admin", 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", "testsubreddit") + form.Set("type", "private") + form.Set("lang", "en") + form.Set("title", "hello!") + form.Set("public_description", "description") + form.Set("description", "sidebar") + form.Set("submit_text", "") + form.Set("welcome_message_text", "") + form.Set("welcome_message_enabled", "false") + form.Set("allow_post_crossposts", "false") + form.Set("allow_chat_post_creation", "true") + form.Set("allow_polls", "false") + form.Set("free_form_reports", "true") + form.Set("original_content_tag_enabled", "false") + form.Set("allow_images", "true") + form.Set("allow_galleries", "true") + form.Set("exclude_banned_modqueue", "false") + form.Set("crowd_control_chat_level", "2") + form.Set("all_original_content", "false") + form.Set("submit_link_label", "submit a link!") + form.Set("submit_text_label", "submit a post!") + form.Set("link_type", "any") + form.Set("spam_links", "low") + form.Set("spam_selfposts", "low") + form.Set("spam_comments", "low") + form.Set("show_media", "false") + form.Set("show_media_preview", "true") + form.Set("collapse_deleted_comments", "false") + form.Set("comment_score_hide_mins", "0") + form.Set("spoilers_enabled", "true") + form.Set("header-title", "hello!") + form.Set("key_color", "") + form.Set("hide_ads", "false") + form.Set("over_18", "false") + form.Set("allow_top", "true") + form.Set("allow_discovery", "true") + form.Set("wikimode", "modonly") + form.Set("wiki_edit_age", "0") + form.Set("wiki_edit_karma", "0") + + err := r.ParseForm() + require.NoError(t, err) + require.Equal(t, form, r.PostForm) + }) + + _, err := client.Subreddit.Create(ctx, "testsubreddit", nil) + require.EqualError(t, err, "*SubredditSettings: cannot be nil") + + _, err = client.Subreddit.Create(ctx, "testsubreddit", expectedSubredditSettings) + require.NoError(t, err) +} + +func TestSubredditService_Edit(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + mux.HandleFunc("/api/site_admin", func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, http.MethodPost, r.Method) + + form := url.Values{} + form.Set("api_type", "json") + form.Set("sr", "t5_test") + form.Set("type", "private") + form.Set("lang", "en") + form.Set("title", "hello!") + form.Set("public_description", "description") + form.Set("description", "sidebar") + form.Set("submit_text", "") + form.Set("welcome_message_text", "") + form.Set("welcome_message_enabled", "false") + form.Set("allow_post_crossposts", "false") + form.Set("allow_chat_post_creation", "true") + form.Set("allow_polls", "false") + form.Set("free_form_reports", "true") + form.Set("original_content_tag_enabled", "false") + form.Set("allow_images", "true") + form.Set("allow_galleries", "true") + form.Set("exclude_banned_modqueue", "false") + form.Set("crowd_control_chat_level", "2") + form.Set("all_original_content", "false") + form.Set("submit_link_label", "submit a link!") + form.Set("submit_text_label", "submit a post!") + form.Set("link_type", "any") + form.Set("spam_links", "low") + form.Set("spam_selfposts", "low") + form.Set("spam_comments", "low") + form.Set("show_media", "false") + form.Set("show_media_preview", "true") + form.Set("collapse_deleted_comments", "false") + form.Set("comment_score_hide_mins", "0") + form.Set("spoilers_enabled", "true") + form.Set("header-title", "hello!") + form.Set("key_color", "") + form.Set("hide_ads", "false") + form.Set("over_18", "false") + form.Set("allow_top", "true") + form.Set("allow_discovery", "true") + form.Set("wikimode", "modonly") + form.Set("wiki_edit_age", "0") + form.Set("wiki_edit_karma", "0") + + err := r.ParseForm() + require.NoError(t, err) + require.Equal(t, form, r.PostForm) + }) + + _, err := client.Subreddit.Edit(ctx, "t5_test", nil) + require.EqualError(t, err, "*SubredditSettings: cannot be nil") + + _, err = client.Subreddit.Edit(ctx, "t5_test", expectedSubredditSettings) + require.NoError(t, err) +} + func TestSubredditService_GetSettings(t *testing.T) { client, mux, teardown := setup() defer teardown() @@ -1602,3 +1758,20 @@ func TestSubredditService_GetSettings(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedSubredditSettings, subredditSettings) } + +func TestSubredditService_PostRequirements(t *testing.T) { + client, mux, teardown := setup() + defer teardown() + + blob, err := readFileContents("../testdata/subreddit/post-requirements.json") + require.NoError(t, err) + + mux.HandleFunc("/api/v1/testsubreddit/post_requirements", func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, http.MethodGet, r.Method) + fmt.Fprint(w, blob) + }) + + postRequirements, _, err := client.Subreddit.PostRequirements(ctx, "testsubreddit") + require.NoError(t, err) + require.Equal(t, expectedSubredditPostRequirements, postRequirements) +} diff --git a/testdata/subreddit/post-requirements.json b/testdata/subreddit/post-requirements.json new file mode 100644 index 0000000..fdc7b05 --- /dev/null +++ b/testdata/subreddit/post-requirements.json @@ -0,0 +1,24 @@ +{ + "title_regexes": [], + "body_blacklisted_strings": ["no"], + "title_blacklisted_strings": ["no"], + "body_text_max_length": 2000, + "title_required_strings": ["yes"], + "guidelines_text": "test", + "gallery_min_items": 2, + "domain_blacklist": ["example.com"], + "domain_whitelist": [], + "title_text_max_length": 200, + "body_restriction_policy": "none", + "link_restriction_policy": "none", + "guidelines_display_policy": null, + "body_required_strings": ["yes"], + "title_text_min_length": 50, + "gallery_captions_requirement": "none", + "is_flair_required": false, + "gallery_max_items": 20, + "gallery_urls_requirement": "none", + "body_regexes": [], + "link_repost_age": 2, + "body_text_min_length": 50 +} \ No newline at end of file