Cleaned up SubredditContent.from_name
This commit is contained in:
@@ -48,6 +48,7 @@ The ``/`` prompt accepts subreddits in the following formats
|
|||||||
* ``python``
|
* ``python``
|
||||||
* ``/r/python``
|
* ``/r/python``
|
||||||
* ``/r/python/new``
|
* ``/r/python/new``
|
||||||
|
* ``/r/python/controversial-year``
|
||||||
* ``/r/python+linux`` supports multireddits
|
* ``/r/python+linux`` supports multireddits
|
||||||
* ``/r/front`` will redirect to the front page
|
* ``/r/front`` will redirect to the front page
|
||||||
* ``/u/me`` will display your submissions
|
* ``/u/me`` will display your submissions
|
||||||
|
|||||||
205
rtv/content.py
205
rtv/content.py
@@ -361,19 +361,10 @@ class SubredditContent(Content):
|
|||||||
list for repeat access.
|
list for repeat access.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, name, submissions, loader, order=None):
|
||||||
self,
|
|
||||||
name,
|
|
||||||
submissions,
|
|
||||||
loader,
|
|
||||||
order=None,
|
|
||||||
listing='r',
|
|
||||||
period=None):
|
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.order = order
|
self.order = order
|
||||||
self.listing = listing
|
|
||||||
self.period = period
|
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
self._submissions = submissions
|
self._submissions = submissions
|
||||||
self._submission_data = []
|
self._submission_data = []
|
||||||
@@ -388,114 +379,136 @@ class SubredditContent(Content):
|
|||||||
raise exceptions.SubredditError('No submissions')
|
raise exceptions.SubredditError('No submissions')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_name(cls, reddit, name, loader, order=None, query=None,
|
def from_name(cls, reddit, name, loader, order=None, query=None):
|
||||||
listing='r', period=None):
|
"""
|
||||||
|
Params:
|
||||||
|
reddit (praw.Reddit): Instance of the reddit api.
|
||||||
|
name (text): The name of the desired subreddit, user, multireddit,
|
||||||
|
etc. In most cases this translates directly from the URL that
|
||||||
|
reddit itself uses. This is what users will type in the command
|
||||||
|
prompt when they navigate to a new location.
|
||||||
|
loader (terminal.loader): Handler for the load screen that will be
|
||||||
|
displayed when making http requests.
|
||||||
|
order (text): If specified, the order that posts will be sorted in.
|
||||||
|
For `top` and `controversial`, you can specify the time frame
|
||||||
|
by including a dash, e.g. "top-year". If an order is not
|
||||||
|
specified, it will be extracted from the name.
|
||||||
|
query (text): Content to search for on the given subreddit or
|
||||||
|
user's page.
|
||||||
|
"""
|
||||||
|
|
||||||
# Strip leading, trailing, and redundant backslashes
|
# Strip leading, trailing, and redundant backslashes
|
||||||
name_list = [seg for seg in name.strip(' /').split('/') if seg]
|
parts = [seg for seg in name.strip(' /').split('/') if seg]
|
||||||
name_order = None
|
|
||||||
if len(name_list) > 1 and name_list[0] in ['r', 'u', 'user', 'domain']:
|
# Check for the resource type, assume /r/ as the default
|
||||||
listing, name_list = name_list[0], name_list[1:]
|
if len(parts) > 3 and parts[2] == ['m']:
|
||||||
if len(name_list) == 2:
|
# E.g. /u/multi-mod/m/android
|
||||||
name, name_order = name_list
|
resource_root, parts = '/'.join(parts[:3]), parts[3:]
|
||||||
elif len(name_list) in [3, 4] and name_list[1] == 'm':
|
if len(parts) > 1 and parts[0] in ['r', 'u', 'user', 'domain']:
|
||||||
name_order = name_list[3] if name_list[3:4] else name_order
|
resource_root = parts.pop(0)
|
||||||
name = '{0}/m/{2}'.format(*name_list)
|
|
||||||
elif len(name_list) == 1 and name_list[0] != '':
|
|
||||||
name = name_list[0]
|
|
||||||
else:
|
else:
|
||||||
|
resource_root = 'r'
|
||||||
|
|
||||||
|
# There should at most two parts left, the resource and the order
|
||||||
|
if len(parts) == 1:
|
||||||
|
resource, resource_order = parts[0], None
|
||||||
|
elif len(parts) == 2:
|
||||||
|
resource, resource_order = parts
|
||||||
|
else:
|
||||||
|
raise InvalidSubreddit()
|
||||||
|
|
||||||
|
if not resource:
|
||||||
# Praw does not correctly handle empty strings
|
# Praw does not correctly handle empty strings
|
||||||
# https://github.com/praw-dev/praw/issues/615
|
# https://github.com/praw-dev/praw/issues/615
|
||||||
raise InvalidSubreddit()
|
raise InvalidSubreddit()
|
||||||
|
|
||||||
order = order or name_order
|
# If the order was explicitly passed in, it will take priority over
|
||||||
listing = 'u' if name == 'me' else listing
|
# the order that was extracted from the name
|
||||||
display_name = '/{0}/{1}'.format(listing, name)
|
order = order or resource_order
|
||||||
|
|
||||||
time = {t: '_from_' + t for t in ['all', 'day', 'hour',
|
display_order = order
|
||||||
'month', 'week', 'year']}
|
display_name = '/'.join(['', resource_root, resource])
|
||||||
time[None] = ''
|
|
||||||
|
|
||||||
if period not in time.keys():
|
# Split the order from the period E.g. controversial-all, top-hour
|
||||||
raise exceptions.SubredditError('Unrecognized period "%s"'
|
if order and '-' in order:
|
||||||
% period)
|
order, period = order.split('-', 1)
|
||||||
|
else:
|
||||||
|
period = None
|
||||||
|
|
||||||
elif order not in ['hot', 'top', 'rising', 'new',
|
if order not in ['hot', 'top', 'rising', 'new', 'controversial', None]:
|
||||||
'controversial', None]:
|
raise InvalidSubreddit('Invalid order "%s"' % order)
|
||||||
raise exceptions.SubredditError('Unrecognized order "%s"' % order)
|
if period not in ['all', 'day', 'hour', 'month', 'week', 'year', None]:
|
||||||
|
raise InvalidSubreddit('Invalid period "%s"' % period)
|
||||||
|
if period and order not in ['top', 'controversial']:
|
||||||
|
raise InvalidSubreddit('"%s" order does not allow sorting by'
|
||||||
|
'period' % order)
|
||||||
|
|
||||||
|
# On some objects, praw doesn't allow you to pass arguments for the
|
||||||
|
# order and period. Instead you need to call special helper functions
|
||||||
|
# such as Multireddit.get_controversial_from_year(). Build the method
|
||||||
|
# name here for convenience.
|
||||||
|
if period:
|
||||||
|
method_alias = 'get_{0}_from_{1}'.format(order, period)
|
||||||
|
elif order:
|
||||||
|
method_alias = 'get_{0}'.format(order)
|
||||||
|
else:
|
||||||
|
method_alias = 'get_hot'
|
||||||
|
|
||||||
|
# Here's where we start to build the submission generators
|
||||||
if query:
|
if query:
|
||||||
if listing in ['u', 'user'] and '/m/' not in name:
|
if resource_root in ('u', 'user'):
|
||||||
reddit.config.API_PATHS['search'] = 'r/{subreddit}/search'
|
search = '/r/{subreddit}/search'
|
||||||
if name == 'me' and reddit.is_oauth_session():
|
author = reddit.user.name if resource == 'me' else resource
|
||||||
query = 'author:{0} {1}'.format(reddit.get_me().name, query)
|
query = 'author:{0} {1}'.format(author, query)
|
||||||
else:
|
subreddit = None
|
||||||
query = 'author:{0} {1}'.format(name, query)
|
|
||||||
location = None
|
|
||||||
else:
|
else:
|
||||||
reddit.config.API_PATHS['search'] = \
|
search = resource_root + '/{{subreddit}}/search'
|
||||||
'{}/{{subreddit}}/search'.format(listing)
|
subreddit = None if resource == 'front' else resource
|
||||||
location = None if name == 'front' else name
|
|
||||||
|
|
||||||
submissions = reddit.search(query, subreddit=location, sort=order,
|
reddit.config.API_PATHS['search'] = search
|
||||||
period=period)
|
submissions = reddit.search(query, subreddit=subreddit,
|
||||||
|
sort=order, period=period)
|
||||||
|
|
||||||
|
elif resource_root == 'domain':
|
||||||
|
order = order or 'hot'
|
||||||
|
submissions = reddit.get_domain_listing(
|
||||||
|
resource, sort=order, period=period, limit=None)
|
||||||
|
|
||||||
elif listing == 'domain':
|
elif resource_root.endswith('/m'):
|
||||||
submissions = reddit.get_domain_listing(name,
|
redditor, _, multi = resource_root.split('/')
|
||||||
sort=(order or 'hot'), period=period)
|
multireddit = reddit.get_multireddit(redditor, multi)
|
||||||
|
submissions = getattr(multireddit, method_alias)(limit=None)
|
||||||
|
|
||||||
elif listing in ['u', 'user']:
|
elif resource_root in ('u', 'user') and resource == 'me':
|
||||||
if '/m/' in name:
|
if not reddit.is_oauth_session():
|
||||||
multireddit = reddit.get_multireddit(*name.split('/')[::2])
|
raise exceptions.AccountError('Not logged in')
|
||||||
if order in ['top', 'controversial']:
|
|
||||||
submissions = eval('multireddit.get_{0}{1}(limit=None)' \
|
|
||||||
.format((order), time[period]))
|
|
||||||
else:
|
|
||||||
submissions = eval('multireddit.get_{0}(limit=None)' \
|
|
||||||
.format((order or 'hot')))
|
|
||||||
|
|
||||||
elif name == 'me':
|
|
||||||
if not reddit.is_oauth_session():
|
|
||||||
raise exceptions.AccountError('Not logged in')
|
|
||||||
else:
|
|
||||||
submissions = reddit.user.get_submitted( \
|
|
||||||
sort=(order or 'new'))
|
|
||||||
else:
|
else:
|
||||||
redditor = reddit.get_redditor(name)
|
order = order or 'new'
|
||||||
submissions = redditor.get_submitted(sort=(order or 'new'),
|
submissions = reddit.user.get_submitted(sort=order, limit=None)
|
||||||
time=(period or 'all'))
|
|
||||||
|
|
||||||
elif listing == 'r':
|
elif resource_root in ('u', 'user'):
|
||||||
if name == 'front':
|
order = order or 'new'
|
||||||
dispatch = {
|
period = period or 'all'
|
||||||
None: reddit.get_front_page,
|
redditor = reddit.get_redditor(resource)
|
||||||
'hot': reddit.get_front_page,
|
submissions = redditor.get_submitted(
|
||||||
'top': eval('reddit.get_top' + time[period]),
|
sort=order, time=period, limit=None)
|
||||||
'rising': reddit.get_rising,
|
|
||||||
'new': reddit.get_new,
|
|
||||||
'controversial': eval('reddit.get_controversial' \
|
|
||||||
+ time[period]),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
elif resource == 'front':
|
||||||
|
if order in (None, 'hot'):
|
||||||
|
submissions = reddit.get_front_page(limit=None)
|
||||||
else:
|
else:
|
||||||
subreddit = reddit.get_subreddit(name)
|
submissions = getattr(reddit, method_alias)(limit=None)
|
||||||
# For special subreddits like /r/random we want to replace the
|
|
||||||
# display name with the one returned by the request.
|
|
||||||
display_name = '/r/{0}'.format(subreddit.display_name)
|
|
||||||
dispatch = {
|
|
||||||
None: subreddit.get_hot,
|
|
||||||
'hot': subreddit.get_hot,
|
|
||||||
'top': eval('subreddit.get_top' + time[period]),
|
|
||||||
'rising': subreddit.get_rising,
|
|
||||||
'new': subreddit.get_new,
|
|
||||||
'controversial': eval('subreddit.get_controversial' \
|
|
||||||
+ time[period]),
|
|
||||||
}
|
|
||||||
submissions = dispatch[order](limit=None)
|
|
||||||
|
|
||||||
return cls(display_name, submissions, loader, order=order,
|
else:
|
||||||
listing=listing, period=period)
|
subreddit = reddit.get_subreddit(resource)
|
||||||
|
submissions = getattr(subreddit, method_alias)(limit=None)
|
||||||
|
|
||||||
|
# For special subreddits like /r/random we want to replace the
|
||||||
|
# display name with the one returned by the request.
|
||||||
|
display_name = '/r/{0}'.format(subreddit.display_name)
|
||||||
|
|
||||||
|
# We made it!
|
||||||
|
return cls(display_name, submissions, loader, order=display_order)
|
||||||
|
|
||||||
def get(self, index, n_cols=70):
|
def get(self, index, n_cols=70):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -323,7 +323,8 @@ class Page(object):
|
|||||||
text = spacing.join(items)
|
text = spacing.join(items)
|
||||||
self.term.add_line(window, text, 0, 0)
|
self.term.add_line(window, text, 0, 0)
|
||||||
if self.content.order is not None:
|
if self.content.order is not None:
|
||||||
col = text.find(self.content.order) - 3
|
order = self.content.order.split('-')[0]
|
||||||
|
col = text.find(order) - 3
|
||||||
window.chgat(0, col, 3, attr | curses.A_REVERSE)
|
window.chgat(0, col, 3, attr | curses.A_REVERSE)
|
||||||
|
|
||||||
self._row += 1
|
self._row += 1
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ class SubscriptionPage(Page):
|
|||||||
super(SubscriptionPage, self).__init__(reddit, term, config, oauth)
|
super(SubscriptionPage, self).__init__(reddit, term, config, oauth)
|
||||||
|
|
||||||
self.controller = SubscriptionController(self, keymap=config.keymap)
|
self.controller = SubscriptionController(self, keymap=config.keymap)
|
||||||
self.content = SubscriptionContent.from_user(reddit, term.loader,
|
self.content = SubscriptionContent.from_user(
|
||||||
content_type)
|
reddit, term.loader, content_type)
|
||||||
self.nav = Navigator(self.content.get)
|
self.nav = Navigator(self.content.get)
|
||||||
self.content_type = content_type
|
self.content_type = content_type
|
||||||
self.subreddit_data = None
|
self.subreddit_data = None
|
||||||
|
|||||||
Reference in New Issue
Block a user