diff --git a/r2/r2/config/routing.py b/r2/r2/config/routing.py index 311eda370..ea9b12a6c 100644 --- a/r2/r2/config/routing.py +++ b/r2/r2/config/routing.py @@ -102,7 +102,8 @@ def make_map(config): mc('/subreddits/login', controller='forms', action='login') mc('/subreddits/:where', controller='reddits', action='listing', where='popular', conditions={'function':not_in_sr}, - requirements=dict(where="popular|new|banned|employee|gold|default|quarantine")) + requirements=dict(where="popular|new|banned|employee|gold|default|" + "quarantine|featured")) # If no subreddit is specified, might as well show a list of 'em. mc('/r', controller='redirect', action='redirect', dest='/subreddits') diff --git a/r2/r2/controllers/listingcontroller.py b/r2/r2/controllers/listingcontroller.py index 1c2d33b0a..00f1ea845 100644 --- a/r2/r2/controllers/listingcontroller.py +++ b/r2/r2/controllers/listingcontroller.py @@ -1453,6 +1453,11 @@ class RedditsController(ListingController): def keep_fn(self): base_keep_fn = ListingController.keep_fn(self) def keep(item): + if self.where == 'featured': + if item.type not in ('public', 'restricted'): + return False + if not item.discoverable: + return False return base_keep_fn(item) and (c.over18 or not item.over_18) return keep @@ -1510,6 +1515,11 @@ class RedditsController(ListingController): sr._fullname for sr in Subreddit.default_subreddits(ids=False) ] + elif self.where == 'featured': + return [ + sr._fullname + for sr in Subreddit.featured_subreddits() + ] else: reddits = Subreddit._query( write_cache = True, read_cache = True, diff --git a/r2/r2/lib/menus.py b/r2/r2/lib/menus.py index 5e2901d42..e100826c0 100644 --- a/r2/r2/lib/menus.py +++ b/r2/r2/lib/menus.py @@ -153,6 +153,7 @@ menu = MenuHandler(hot = _('hot'), create = _("create"), mine = _("my subreddits"), quarantine = _("quarantine"), + featured = _("featured"), i18n = _("help translate"), errors = _("errors"), diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index 45977059e..e846a41eb 100644 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -2245,6 +2245,8 @@ class SubredditsPage(Reddit): buttons.append(NamedButton("gold")) if c.user_is_admin: buttons.append(NamedButton("quarantine")) + if c.user_is_admin: + buttons.append(NamedButton("featured")) if c.user_is_loggedin: #add the aliases to "my reddits" stays highlighted buttons.append(NamedButton("mine", diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index 3a742b4f2..bdc77ba8e 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -1056,6 +1056,17 @@ class Subreddit(Thing, Printable, BaseSite): else: return srs + @classmethod + def featured_subreddits(cls): + """Return the curated list of subreddits shown during onboarding.""" + location = get_user_location() + srids = LocalizedFeaturedSubreddits.get_featured(location) + + srs = Subreddit._byID(srids, data=True, return_dict=False, stale=True) + srs = filter(lambda sr: sr.discoverable, srs) + + return srs + @classmethod @memoize('random_reddits', time = 1800) def random_reddits_cached(cls, user_name, sr_ids, limit): @@ -1971,9 +1982,9 @@ class TooManySubredditsError(Exception): pass -class LocalizedDefaultSubreddits(tdb_cassandra.View): +class BaseLocalizedSubreddits(tdb_cassandra.View): """Mapping of location to subreddit ids""" - _use_db = True + _use_db = False _compare_with = tdb_cassandra.ASCII_TYPE _read_consistency_level = tdb_cassandra.CL.QUORUM _write_consistency_level = tdb_cassandra.CL.QUORUM @@ -1982,7 +1993,6 @@ class LocalizedDefaultSubreddits(tdb_cassandra.View): "default_validation_class": tdb_cassandra.ASCII_TYPE, } GLOBAL = "GLOBAL" - CACHE_PREFIX = "localized_defaults" @classmethod def _rowkey(cls, location): @@ -2046,7 +2056,7 @@ class LocalizedDefaultSubreddits(tdb_cassandra.View): return cls.get_srids(cls.GLOBAL) @classmethod - def get_defaults(cls, location): + def get_localized_srs(cls, location): location_key = cls._rowkey(location) if location else None global_key = cls._rowkey(cls.GLOBAL) keys = filter(None, [location_key, global_key]) @@ -2060,6 +2070,26 @@ class LocalizedDefaultSubreddits(tdb_cassandra.View): return ids_by_location[global_key] +class LocalizedDefaultSubreddits(BaseLocalizedSubreddits): + _use_db = True + _type_prefix = "LocalizedDefaultSubreddits" + CACHE_PREFIX = "localized_defaults" + + @classmethod + def get_defaults(cls, location): + return cls.get_localized_srs(location) + + +class LocalizedFeaturedSubreddits(BaseLocalizedSubreddits): + _use_db = True + _type_prefix = "LocalizedFeaturedSubreddits" + CACHE_PREFIX = "localized_featured" + + @classmethod + def get_featured(cls, location): + return cls.get_localized_srs(location) + + class LabeledMulti(tdb_cassandra.Thing, MultiReddit): """Thing with special columns that hold Subreddit ids and properties.""" _use_db = True diff --git a/scripts/inject_test_data.py b/scripts/inject_test_data.py index 14d651842..db5f96e57 100644 --- a/scripts/inject_test_data.py +++ b/scripts/inject_test_data.py @@ -42,6 +42,7 @@ from r2.models import ( Comment, Link, LocalizedDefaultSubreddits, + LocalizedFeaturedSubreddits, NotFound, register, Subreddit, @@ -356,3 +357,4 @@ def inject_test_data(num_links=25, num_comments=25, num_votes=5): srs = [Subreddit._by_name(n) for n in ("pics", "videos", "askhistorians")] LocalizedDefaultSubreddits.set_global_srs(srs) + LocalizedFeaturedSubreddits.set_global_srs([Subreddit._by_name('pics')])