mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-27 07:48:16 -05:00
Add documentation examples to flesh out api_docs.
This commit is contained in:
@@ -54,6 +54,7 @@ from r2.lib.subreddit_search import search_reddits
|
||||
from r2.lib.log import log_text
|
||||
from r2.lib.filters import safemarkdown
|
||||
from r2.lib.scraper import str_to_image
|
||||
from r2.controllers.api_docs import api_doc, api_section
|
||||
|
||||
import csv
|
||||
from collections import defaultdict
|
||||
@@ -76,12 +77,14 @@ def reject_vote(thing):
|
||||
(voteword, c.user.name, request.ip, thing.__class__.__name__,
|
||||
thing._id36, request.referer), "info")
|
||||
|
||||
|
||||
class ApiminimalController(MinimalController):
|
||||
"""
|
||||
Put API calls in here which don't rely on the user being logged in
|
||||
"""
|
||||
|
||||
@validatedForm()
|
||||
@api_doc(api_section.misc)
|
||||
def POST_new_captcha(self, form, jquery, *a, **kw):
|
||||
iden = get_iden()
|
||||
jquery("body").captcha(iden)
|
||||
@@ -100,6 +103,7 @@ class ApiController(RedditController):
|
||||
@validate(link1 = VUrl(['url']),
|
||||
link2 = VByName('id'),
|
||||
count = VLimit('limit'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def GET_info(self, link1, link2, count):
|
||||
"""
|
||||
Gets a listing of links which have the provided url.
|
||||
@@ -115,7 +119,13 @@ class ApiController(RedditController):
|
||||
|
||||
|
||||
@json_validate()
|
||||
@api_doc(api_section.account, extensions=["json"])
|
||||
def GET_me(self, responder):
|
||||
"""
|
||||
Get info about the currently authenticated user.
|
||||
|
||||
Response includes a modhash, karma, and new mail status.
|
||||
"""
|
||||
if c.user_is_loggedin:
|
||||
return Wrapped(c.user).render()
|
||||
else:
|
||||
@@ -155,6 +165,7 @@ class ApiController(RedditController):
|
||||
to = VMessageRecipient('to'),
|
||||
subject = VRequired('subject', errors.NO_SUBJECT),
|
||||
body = VMarkdown(['text', 'message']))
|
||||
@api_doc(api_section.messages)
|
||||
def POST_compose(self, form, jquery, to, subject, body, ip):
|
||||
"""
|
||||
handles message composition under /message/compose.
|
||||
@@ -186,6 +197,7 @@ class ApiController(RedditController):
|
||||
then = VOneOf('then', ('tb', 'comments'),
|
||||
default='comments'),
|
||||
extension = VLength("extension", 20))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_submit(self, form, jquery, url, selftext, kind, title,
|
||||
save, sr, ip, then, extension):
|
||||
from r2.models.admintools import is_banned_domain
|
||||
@@ -373,10 +385,12 @@ class ApiController(RedditController):
|
||||
responder._send_data(cookie = user.make_cookie())
|
||||
|
||||
@cross_domain(allow_credentials=True)
|
||||
@api_doc(api_section.account)
|
||||
def POST_login(self, *args, **kwargs):
|
||||
return self._handle_login(*args, **kwargs)
|
||||
|
||||
@cross_domain(allow_credentials=True)
|
||||
@api_doc(api_section.account)
|
||||
def POST_register(self, *args, **kwargs):
|
||||
return self._handle_register(*args, **kwargs)
|
||||
|
||||
@@ -430,6 +444,7 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
container = VByName('id'))
|
||||
@api_doc(api_section.moderation)
|
||||
def POST_leavemoderator(self, container):
|
||||
"""
|
||||
Handles self-removal as moderator from a subreddit as rendered
|
||||
@@ -444,6 +459,7 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
container = VByName('id'))
|
||||
@api_doc(api_section.moderation)
|
||||
def POST_leavecontributor(self, container):
|
||||
"""
|
||||
same comment as for POST_leave_moderator.
|
||||
@@ -459,6 +475,7 @@ class ApiController(RedditController):
|
||||
container = VByName('container'),
|
||||
type = VOneOf('type', ('friend', 'enemy', 'moderator',
|
||||
'contributor', 'banned')))
|
||||
@api_doc(api_section.users)
|
||||
def POST_unfriend(self, nuser, iuser, container, type):
|
||||
"""
|
||||
Handles removal of a friend (a user-user relation) or removal
|
||||
@@ -507,6 +524,7 @@ class ApiController(RedditController):
|
||||
type = VOneOf('type', ('friend', 'moderator',
|
||||
'contributor', 'banned')),
|
||||
note = VLength('note', 300))
|
||||
@api_doc(api_section.users)
|
||||
def POST_friend(self, form, jquery, ip, friend,
|
||||
container, type, note):
|
||||
"""
|
||||
@@ -597,8 +615,13 @@ class ApiController(RedditController):
|
||||
VModhash(),
|
||||
password = VPassword(['curpass', 'curpass']),
|
||||
dest = VDestination())
|
||||
@api_doc(api_section.account)
|
||||
def POST_clear_sessions(self, form, jquery, password, dest):
|
||||
"""Clear all session cookies and update the current one."""
|
||||
"""
|
||||
Clear all session cookies and update the current one.
|
||||
|
||||
A valid password (`curpass`) must be supplied.
|
||||
"""
|
||||
# password is required to proceed
|
||||
if form.has_errors("curpass", errors.WRONG_PASSWORD):
|
||||
return
|
||||
@@ -617,9 +640,14 @@ class ApiController(RedditController):
|
||||
email = ValidEmails("email", num = 1),
|
||||
password = VPassword(['newpass', 'verpass']),
|
||||
verify = VBoolean("verify"))
|
||||
@api_doc(api_section.account)
|
||||
def POST_update(self, form, jquery, email, password, verify):
|
||||
"""
|
||||
handles /prefs/update for updating email address and password.
|
||||
Update account email address and password.
|
||||
|
||||
Called by /prefs/update on the site. For frontend form verification
|
||||
purposes, `newpass` and `verpass` must be equal for a password change
|
||||
to succeed.
|
||||
"""
|
||||
# password is required to proceed
|
||||
if form.has_errors("curpass", errors.WRONG_PASSWORD):
|
||||
@@ -678,9 +706,16 @@ class ApiController(RedditController):
|
||||
username = VRequired("user", errors.NOT_USER),
|
||||
user = VThrottledLogin(["user", "passwd"]),
|
||||
confirm = VBoolean("confirm"))
|
||||
@api_doc(api_section.account)
|
||||
def POST_delete_user(self, form, jquery, delete_message, username, user, confirm):
|
||||
"""
|
||||
/prefs/delete. Check the username/password and confirmation.
|
||||
Delete an account.
|
||||
|
||||
A valid username/password and confirmation must be supplied. An
|
||||
optional `delete_message` may be supplied to explain the reason the
|
||||
account is to be deleted.
|
||||
|
||||
Called by /prefs/delete on the site.
|
||||
"""
|
||||
if username and username.lower() != c.user.name.lower():
|
||||
c.errors.add(errors.NOT_USER, field="user")
|
||||
@@ -746,6 +781,7 @@ class ApiController(RedditController):
|
||||
VModhash(),
|
||||
VSrCanAlter('id'),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_marknsfw(self, thing):
|
||||
thing.over_18 = True
|
||||
thing._commit()
|
||||
@@ -761,6 +797,7 @@ class ApiController(RedditController):
|
||||
VModhash(),
|
||||
VSrCanAlter('id'),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_unmarknsfw(self, thing):
|
||||
thing.over_18 = False
|
||||
thing._commit()
|
||||
@@ -774,6 +811,7 @@ class ApiController(RedditController):
|
||||
|
||||
@noresponse(VUser(), VModhash(),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_report(self, thing):
|
||||
'''for reporting...'''
|
||||
if not thing or thing._deleted:
|
||||
@@ -800,6 +838,7 @@ class ApiController(RedditController):
|
||||
|
||||
@noresponse(VUser(), VModhash(),
|
||||
thing=VByName('id'))
|
||||
@api_doc(api_section.messages)
|
||||
def POST_block(self, thing):
|
||||
'''for blocking via inbox'''
|
||||
if not thing:
|
||||
@@ -841,6 +880,7 @@ class ApiController(RedditController):
|
||||
VModhash(),
|
||||
item = VByNameIfAuthor('thing_id'),
|
||||
text = VSelfText('text'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_editusertext(self, form, jquery, item, text):
|
||||
if (not form.has_errors("text",
|
||||
errors.NO_TEXT, errors.TOO_LONG) and
|
||||
@@ -880,6 +920,7 @@ class ApiController(RedditController):
|
||||
ip = ValidIP(),
|
||||
parent = VSubmitParent(['thing_id', 'parent']),
|
||||
comment = VMarkdown(['text', 'comment']))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_comment(self, commentform, jquery, parent, comment, ip):
|
||||
should_ratelimit = True
|
||||
#check the parent type here cause we need that for the
|
||||
@@ -1065,6 +1106,7 @@ class ApiController(RedditController):
|
||||
ip = ValidIP(),
|
||||
dir = VInt('dir', min=-1, max=1),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_vote(self, dir, thing, ip, vote_type):
|
||||
ip = request.ip
|
||||
user = c.user
|
||||
@@ -1098,6 +1140,7 @@ class ApiController(RedditController):
|
||||
# nop is safe: handled after auth checks below
|
||||
stylesheet_contents = nop('stylesheet_contents'),
|
||||
op = VOneOf('op',['save','preview']))
|
||||
@api_doc(api_section.subreddits)
|
||||
def POST_subreddit_stylesheet(self, form, jquery,
|
||||
stylesheet_contents = '', op='save'):
|
||||
if not c.site.can_change_stylesheet(c.user):
|
||||
@@ -1171,6 +1214,7 @@ class ApiController(RedditController):
|
||||
@validatedForm(VSrModerator(),
|
||||
VModhash(),
|
||||
name = VCssName('img_name'))
|
||||
@api_doc(api_section.subreddits)
|
||||
def POST_delete_sr_img(self, form, jquery, name):
|
||||
"""
|
||||
Called called upon requested delete on /about/stylesheet.
|
||||
@@ -1188,6 +1232,7 @@ class ApiController(RedditController):
|
||||
@validatedForm(VSrModerator(),
|
||||
VModhash(),
|
||||
sponsor = VInt("sponsor", min = 0, max = 1))
|
||||
@api_doc(api_section.subreddits)
|
||||
def POST_delete_sr_header(self, form, jquery, sponsor):
|
||||
"""
|
||||
Called when the user request that the header on a sr be reset.
|
||||
@@ -1235,6 +1280,7 @@ class ApiController(RedditController):
|
||||
form_id = VLength('formid', max_length = 100),
|
||||
header = VInt('header', max=1, min=0),
|
||||
sponsor = VSubredditSponsorship('sponsor'))
|
||||
@api_doc(api_section.subreddits)
|
||||
def POST_upload_sr_img(self, file, header, sponsor, name, form_id, img_type):
|
||||
"""
|
||||
Called on /about/stylesheet when an image needs to be replaced
|
||||
@@ -1323,6 +1369,7 @@ class ApiController(RedditController):
|
||||
sponsor_url = VLength('sponsorship-url', max_length = 500),
|
||||
css_on_cname = VBoolean("css_on_cname"),
|
||||
)
|
||||
@api_doc(api_section.subreddits)
|
||||
def POST_site_admin(self, form, jquery, name, ip, sr,
|
||||
sponsor_text, sponsor_url, sponsor_name, **kw):
|
||||
# the status button is outside the form -- have to reset by hand
|
||||
@@ -1441,6 +1488,7 @@ class ApiController(RedditController):
|
||||
why = VSrCanBan('id'),
|
||||
thing = VByName('id'),
|
||||
spam = VBoolean('spam', default=True))
|
||||
@api_doc(api_section.moderation)
|
||||
def POST_remove(self, why, thing, spam):
|
||||
|
||||
# Don't remove a promoted link
|
||||
@@ -1479,6 +1527,7 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(), VModhash(),
|
||||
why = VSrCanBan('id'),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.moderation)
|
||||
def POST_approve(self, why, thing):
|
||||
if not thing: return
|
||||
if thing._deleted: return
|
||||
@@ -1502,6 +1551,7 @@ class ApiController(RedditController):
|
||||
VCanDistinguish(('id', 'how')),
|
||||
thing = VByName('id'),
|
||||
how = VOneOf('how', ('yes','no','admin','special')))
|
||||
@api_doc(api_section.moderation)
|
||||
def POST_distinguish(self, form, jquery, thing, how):
|
||||
if not thing:return
|
||||
|
||||
@@ -1532,6 +1582,7 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_save(self, thing):
|
||||
if not thing: return
|
||||
r = thing._save(c.user)
|
||||
@@ -1541,6 +1592,7 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_unsave(self, thing):
|
||||
if not thing: return
|
||||
r = thing._unsave(c.user)
|
||||
@@ -1619,18 +1671,21 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
things = VByName('id', multiple=True, limit=25))
|
||||
@api_doc(api_section.messages)
|
||||
def POST_unread_message(self, things):
|
||||
self.unread_handler(things, True)
|
||||
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
things = VByName('id', multiple=True, limit=25))
|
||||
@api_doc(api_section.messages)
|
||||
def POST_read_message(self, things):
|
||||
self.unread_handler(things, False)
|
||||
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_hide(self, thing):
|
||||
if not thing: return
|
||||
r = thing._hide(c.user)
|
||||
@@ -1640,6 +1695,7 @@ class ApiController(RedditController):
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
thing = VByName('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_unhide(self, thing):
|
||||
if not thing: return
|
||||
r = thing._unhide(c.user)
|
||||
@@ -1674,6 +1730,7 @@ class ApiController(RedditController):
|
||||
children = VCommentIDs('children'),
|
||||
pv_hex = VPrintable('pv_hex', 40),
|
||||
mc_id = nop('id'))
|
||||
@api_doc(api_section.links_and_comments)
|
||||
def POST_morechildren(self, form, jquery, link, sort, children,
|
||||
pv_hex, mc_id):
|
||||
user = c.user if c.user_is_loggedin else None
|
||||
@@ -1879,6 +1936,7 @@ class ApiController(RedditController):
|
||||
VModhash(),
|
||||
action = VOneOf('action', ('sub', 'unsub')),
|
||||
sr = VSubscribeSR('sr', 'sr_name'))
|
||||
@api_doc(api_section.subreddits)
|
||||
def POST_subscribe(self, action, sr):
|
||||
# only users who can make edits are allowed to subscribe.
|
||||
# Anyone can leave.
|
||||
@@ -2055,6 +2113,7 @@ class ApiController(RedditController):
|
||||
prefer_existing=True),
|
||||
text = VFlairText("text"),
|
||||
css_class = VFlairCss("css_class"))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_flair(self, form, jquery, user, text, css_class):
|
||||
# Check validation.
|
||||
if form.has_errors('name', errors.USER_DOESNT_EXIST, errors.NO_USER):
|
||||
@@ -2103,6 +2162,7 @@ class ApiController(RedditController):
|
||||
VModhash(),
|
||||
user = VExistingUname("name", allow_deleted=True,
|
||||
prefer_existing=True))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_deleteflair(self, form, jquery, user):
|
||||
# Check validation.
|
||||
if form.has_errors('name', errors.USER_DOESNT_EXIST, errors.NO_USER):
|
||||
@@ -2123,6 +2183,7 @@ class ApiController(RedditController):
|
||||
@validate(VFlairManager(),
|
||||
VModhash(),
|
||||
flair_csv = nop('flair_csv'))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_flaircsv(self, flair_csv):
|
||||
limit = 100 # max of 100 flair settings per call
|
||||
results = FlairCsv()
|
||||
@@ -2190,6 +2251,7 @@ class ApiController(RedditController):
|
||||
@validatedForm(VUser(),
|
||||
VModhash(),
|
||||
flair_enabled = VBoolean("flair_enabled"))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_setflairenabled(self, form, jquery, flair_enabled):
|
||||
setattr(c.user, 'flair_%s_enabled' % c.site._id, flair_enabled)
|
||||
c.user._commit()
|
||||
@@ -2201,6 +2263,7 @@ class ApiController(RedditController):
|
||||
flair_enabled = VBoolean("flair_enabled"),
|
||||
flair_position = VOneOf("flair_position", ("left", "right")),
|
||||
flair_self_assign_enabled = VBoolean("flair_self_assign_enabled"))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_flairconfig(self, form, jquery, flair_enabled, flair_position,
|
||||
flair_self_assign_enabled):
|
||||
if c.site.flair_enabled != flair_enabled:
|
||||
@@ -2222,6 +2285,7 @@ class ApiController(RedditController):
|
||||
@validate(VFlairManager(),
|
||||
user = VOptionalExistingUname('name', allow_deleted=True,
|
||||
prefer_existing=True))
|
||||
@api_doc(api_section.flair)
|
||||
def GET_flairlist(self, num, after, reverse, count, user):
|
||||
flair = FlairList(num, after, reverse, '', user)
|
||||
return BoringPage(_("API"), content = flair).render()
|
||||
@@ -2232,6 +2296,7 @@ class ApiController(RedditController):
|
||||
text = VFlairText('text'),
|
||||
css_class = VFlairCss('css_class'),
|
||||
text_editable = VBoolean('text_editable'))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_flairtemplate(self, form, jquery, flair_template, text,
|
||||
css_class, text_editable):
|
||||
if text is None:
|
||||
@@ -2286,6 +2351,7 @@ class ApiController(RedditController):
|
||||
@validatedForm(VFlairManager(),
|
||||
VModhash(),
|
||||
flair_template = VFlairTemplateByID('flair_template_id'))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_deleteflairtemplate(self, form, jquery, flair_template):
|
||||
idx = FlairTemplateBySubredditIndex.by_sr(c.site._id)
|
||||
if idx.delete_by_id(flair_template._id):
|
||||
@@ -2294,6 +2360,7 @@ class ApiController(RedditController):
|
||||
details='flair_delete_template')
|
||||
|
||||
@validatedForm(VFlairManager(), VModhash())
|
||||
@api_doc(api_section.flair)
|
||||
def POST_clearflairtemplates(self, form, jquery):
|
||||
FlairTemplateBySubredditIndex.clear(c.site._id)
|
||||
jquery.refresh()
|
||||
@@ -2313,6 +2380,7 @@ class ApiController(RedditController):
|
||||
user = VOptionalExistingUname('name'),
|
||||
flair_template = VFlairTemplateByID('flair_template_id'),
|
||||
text = VFlairText("text"))
|
||||
@api_doc(api_section.flair)
|
||||
def POST_selectflair(self, form, jquery, user, flair_template, text):
|
||||
if not flair_template:
|
||||
# TODO: serve error to client
|
||||
|
||||
@@ -46,6 +46,7 @@ from r2.lib import sup
|
||||
import r2.lib.db.thing as thing
|
||||
from errors import errors
|
||||
from listingcontroller import ListingController
|
||||
from api_docs import api_doc, api_section
|
||||
from pylons import c, request, request, Response
|
||||
|
||||
import string
|
||||
@@ -86,6 +87,7 @@ class FrontController(RedditController):
|
||||
# redirect should be smarter and handle extensions, etc.
|
||||
return self.redirect(new_url, code=301)
|
||||
|
||||
@api_doc(api_section.listings)
|
||||
def GET_random(self):
|
||||
"""The Serendipity button"""
|
||||
sort = rand.choice(('new','hot'))
|
||||
@@ -179,6 +181,9 @@ class FrontController(RedditController):
|
||||
sort = VMenu('controller', CommentSortMenu),
|
||||
limit = VInt('limit'),
|
||||
depth = VInt('depth'))
|
||||
@api_doc(api_section.listings,
|
||||
uri='/comments/{article}',
|
||||
extensions=['json', 'xml'])
|
||||
def GET_comments(self, article, comment, context, sort, limit, depth):
|
||||
"""Comment page for a given 'article'."""
|
||||
if comment and comment.link_id != article._id:
|
||||
@@ -388,6 +393,7 @@ class FrontController(RedditController):
|
||||
@paginated_listing(max_page_size=500, backend='cassandra')
|
||||
@validate(mod=VAccountByName('mod'),
|
||||
action=VOneOf('type', ModAction.actions))
|
||||
@api_doc(api_section.moderation)
|
||||
def GET_moderationlog(self, num, after, reverse, count, mod, action):
|
||||
if not c.user_is_loggedin:
|
||||
return self.abort404()
|
||||
@@ -606,6 +612,7 @@ class FrontController(RedditController):
|
||||
return self._edit_normal_reddit(location, num, after, reverse,
|
||||
count, created, name, user)
|
||||
|
||||
@api_doc(api_section.subreddits, uri='/r/{subreddit}/about', extensions=['json'])
|
||||
def GET_about(self):
|
||||
"""Return information about the subreddit.
|
||||
|
||||
@@ -670,6 +677,7 @@ class FrontController(RedditController):
|
||||
|
||||
@base_listing
|
||||
@validate(query = nop('q'))
|
||||
@api_doc(api_section.subreddits, uri='/reddits/search', extensions=['json', 'xml'])
|
||||
def GET_search_reddits(self, query, reverse, after, count, num):
|
||||
"""Search reddits by title and description."""
|
||||
q = SubredditSearchQuery(query)
|
||||
@@ -692,6 +700,7 @@ class FrontController(RedditController):
|
||||
@validate(query = VLength('q', max_length=512),
|
||||
sort = VMenu('sort', SearchSortMenu, remember=False),
|
||||
restrict_sr = VBoolean('restrict_sr', default=False))
|
||||
@api_doc(api_section.search, extensions=['json', 'xml'])
|
||||
def GET_search(self, query, num, reverse, after, count, sort, restrict_sr):
|
||||
"""Search links page."""
|
||||
if query and '.' in query:
|
||||
|
||||
@@ -44,12 +44,14 @@ from r2.lib import sup
|
||||
from r2.lib.promote import randomized_promotion_list, get_promote_srid
|
||||
import socket
|
||||
|
||||
from api_docs import api_doc, api_section
|
||||
from admin import admin_profile_query
|
||||
|
||||
from pylons.i18n import _
|
||||
from pylons import Response
|
||||
|
||||
import random
|
||||
from functools import partial
|
||||
|
||||
class ListingController(RedditController):
|
||||
"""Generalized controller for pages with lists of links."""
|
||||
@@ -180,10 +182,13 @@ class ListingController(RedditController):
|
||||
builder_wrapper = staticmethod(default_thing_wrapper())
|
||||
|
||||
@base_listing
|
||||
@api_doc(api_section.listings, extensions=['json', 'xml'])
|
||||
def GET_listing(self, **env):
|
||||
check_cheating('site')
|
||||
return self.build_listing(**env)
|
||||
|
||||
listing_api_doc = partial(api_doc, section=api_section.listings, extends=ListingController.GET_listing)
|
||||
|
||||
class FixListing(object):
|
||||
"""When sorting by hotness, computing a listing when the before/after
|
||||
link has a hottness of 0 is very slow. This class avoids drawing
|
||||
@@ -337,6 +342,7 @@ class HotController(FixListing, ListingController):
|
||||
def title(self):
|
||||
return c.site.title
|
||||
|
||||
@listing_api_doc(uri='/hot')
|
||||
def GET_listing(self, **env):
|
||||
self.infotext = request.get.get('deleted') and strings.user_deleted
|
||||
return ListingController.GET_listing(self, **env)
|
||||
@@ -350,6 +356,7 @@ class SavedController(ListingController):
|
||||
return queries.get_saved(c.user)
|
||||
|
||||
@validate(VUser())
|
||||
@listing_api_doc(uri='/saved')
|
||||
def GET_listing(self, **env):
|
||||
return ListingController.GET_listing(self, **env)
|
||||
|
||||
@@ -396,6 +403,7 @@ class NewController(ListingController):
|
||||
return self.redirect(request.fullpath + query_string(dict(sort=sort)))
|
||||
|
||||
@validate(sort = VMenu('controller', NewMenu))
|
||||
@listing_api_doc(uri='/new')
|
||||
def GET_listing(self, sort, **env):
|
||||
self.sort = sort
|
||||
return ListingController.GET_listing(self, **env)
|
||||
@@ -433,6 +441,7 @@ class BrowseController(ListingController):
|
||||
# TODO: this is a hack with sort.
|
||||
@validate(sort = VOneOf('sort', ('top', 'controversial')),
|
||||
t = VMenu('sort', ControversyTimeMenu))
|
||||
@listing_api_doc(uri='/{sort}', uri_variants=['/top', '/controversial'])
|
||||
def GET_listing(self, sort, t, **env):
|
||||
self.sort = sort
|
||||
if sort == 'top':
|
||||
@@ -578,6 +587,10 @@ class UserController(ListingController):
|
||||
@validate(vuser = VExistingUname('username'),
|
||||
sort = VMenu('sort', ProfileSortMenu, remember = False),
|
||||
time = VMenu('t', TimeMenu, remember = False))
|
||||
@listing_api_doc(section=api_section.users, uri='/{username}/{where}',
|
||||
uri_variants=['/{username}/' + where for where in [
|
||||
'overview', 'submitted', 'commented',
|
||||
'liked', 'disliked', 'hidden']])
|
||||
def GET_listing(self, where, vuser, sort, time, **env):
|
||||
self.where = where
|
||||
self.sort = sort
|
||||
@@ -613,7 +626,9 @@ class UserController(ListingController):
|
||||
return ListingController.GET_listing(self, **env)
|
||||
|
||||
@validate(vuser = VExistingUname('username'))
|
||||
@api_doc(section=api_section.users, uri='/{username}/about', extensions=['json'])
|
||||
def GET_about(self, vuser):
|
||||
"""Return information about the user, including karma and gold status."""
|
||||
if not is_api() or not vuser:
|
||||
return self.abort404()
|
||||
return Reddit(content = Wrapped(vuser)).render()
|
||||
@@ -766,6 +781,9 @@ class MessageController(ListingController):
|
||||
@validate(VUser(),
|
||||
message = VMessageID('mid'),
|
||||
mark = VOneOf('mark',('true','false')))
|
||||
@listing_api_doc(section=api_section.messages,
|
||||
uri='/message/{where}',
|
||||
uri_variants=['/message/inbox', '/message/unread', '/message/sent'])
|
||||
def GET_listing(self, where, mark, message, subwhere = None, **env):
|
||||
if not (c.default_sr or c.site.is_moderator(c.user) or c.user_is_admin):
|
||||
abort(403, "forbidden")
|
||||
@@ -835,6 +853,10 @@ class RedditsController(ListingController):
|
||||
reddits._filter(Subreddit.c.over_18 == False)
|
||||
|
||||
return reddits
|
||||
|
||||
@listing_api_doc(section=api_section.subreddits,
|
||||
uri='/reddits/{where}',
|
||||
uri_variants=['/reddits/popular', '/reddits/new', '/reddits/banned'])
|
||||
def GET_listing(self, where, **env):
|
||||
self.where = where
|
||||
return ListingController.GET_listing(self, **env)
|
||||
@@ -883,6 +905,9 @@ class MyredditsController(ListingController):
|
||||
return stack
|
||||
|
||||
@validate(VUser())
|
||||
@listing_api_doc(section=api_section.subreddits,
|
||||
uri='/reddits/mine/{where}',
|
||||
uri_variants=['/reddits/mine/subscriber', '/reddits/mine/contributor', '/reddits/mine/moderator'])
|
||||
def GET_listing(self, where = 'inbox', **env):
|
||||
self.where = where
|
||||
return ListingController.GET_listing(self, **env)
|
||||
|
||||
@@ -601,6 +601,11 @@ class VByName(Validator):
|
||||
|
||||
return self.set_error(self._error)
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param: _('an existing thing id')
|
||||
}
|
||||
|
||||
class VByNameIfAuthor(VByName):
|
||||
def run(self, fullname):
|
||||
thing = VByName.run(self, fullname)
|
||||
@@ -637,6 +642,11 @@ class VModhash(Validator):
|
||||
def run(self, uh):
|
||||
pass
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param: _('a modhash')
|
||||
}
|
||||
|
||||
class VVotehash(Validator):
|
||||
def run(self, vh, thing_name):
|
||||
return True
|
||||
@@ -817,6 +827,11 @@ class VSubmitParent(VByName):
|
||||
#else
|
||||
abort(403, "forbidden")
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param[0]: _('id of parent thing')
|
||||
}
|
||||
|
||||
class VSubmitSR(Validator):
|
||||
def __init__(self, srname_param, linktype_param=None, promotion=False):
|
||||
self.require_linktype = False
|
||||
@@ -998,6 +1013,16 @@ class VUrl(VRequired):
|
||||
return url
|
||||
return self.error(errors.BAD_URL)
|
||||
|
||||
def param_docs(self):
|
||||
params = {}
|
||||
try:
|
||||
params[self.param[0]] = _('a valid URL')
|
||||
params[self.param[1]] = _('a subreddit')
|
||||
params[self.param[2]] = _('boolean value')
|
||||
except IndexError:
|
||||
pass
|
||||
return params
|
||||
|
||||
class VOptionalExistingUname(VRequired):
|
||||
def __init__(self, item, allow_deleted=False, prefer_existing=False,
|
||||
*a, **kw):
|
||||
@@ -1038,6 +1063,11 @@ class VExistingUname(VOptionalExistingUname):
|
||||
self.error()
|
||||
return user
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param: _('the name of an existing user')
|
||||
}
|
||||
|
||||
class VMessageRecipient(VExistingUname):
|
||||
def run(self, name):
|
||||
if not name:
|
||||
@@ -1081,6 +1111,11 @@ class VBoolean(Validator):
|
||||
return False
|
||||
return bool(val)
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param: _('boolean value')
|
||||
}
|
||||
|
||||
class VNumber(Validator):
|
||||
def __init__(self, param, min=None, max=None, coerce = True,
|
||||
error = errors.BAD_NUMBER, *a, **kw):
|
||||
@@ -1361,6 +1396,11 @@ class VOneOf(Validator):
|
||||
else:
|
||||
return val
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param: _('one of (%s)') % ', '.join(self.options)
|
||||
}
|
||||
|
||||
class VImageType(Validator):
|
||||
def run(self, img_type):
|
||||
if not img_type in ('png', 'jpg'):
|
||||
@@ -1546,6 +1586,11 @@ class VDestination(Validator):
|
||||
|
||||
return "/"
|
||||
|
||||
def param_docs(self):
|
||||
return {
|
||||
self.param: _('destination url (must be same-domain)')
|
||||
}
|
||||
|
||||
class ValidAddress(Validator):
|
||||
def __init__(self, param, allowed_countries = ["United States"]):
|
||||
self.allowed_countries = allowed_countries
|
||||
|
||||
Reference in New Issue
Block a user