Add backend for new gold feature: "remember my visits".

Store and mark what links users have already read, even between
computers.
This commit is contained in:
David King
2013-10-24 11:57:48 -07:00
committed by Neil Williams
parent a54d977db5
commit ff002a4bce
8 changed files with 55 additions and 24 deletions

View File

@@ -248,7 +248,6 @@ db_table_link = thing
db_table_account = thing
db_table_message = thing
db_table_savehide = relation, account, link
db_table_click = relation, account, link
db_table_comment = thing
db_table_subreddit = thing
db_table_srmember = relation, subreddit, account
@@ -277,7 +276,6 @@ db_servers_link = main, main
db_servers_account = main
db_servers_message = main
db_servers_savehide = main
db_servers_click = main
db_servers_comment = comment
db_servers_subreddit = comment
db_servers_srmember = comment

View File

@@ -3632,3 +3632,12 @@ class ApiController(RedditController, OAuth2ResourceController):
def POST_server_seconds_visibility(self, form, jquery, seconds_visibility):
c.user.pref_public_server_seconds = seconds_visibility == "public"
c.user._commit()
@noresponse(VGold(),
links = VByName('links', thing_cls=Link, multiple=True,
limit=100))
def POST_store_visits(self, links):
if not c.user.pref_store_visits or not links:
return
LinkVisitsByAccount._visit(c.user, links)

View File

@@ -99,6 +99,7 @@ class PostController(ApiController):
pref_collapse_read_messages = VBoolean("collapse_read_messages"),
pref_private_feeds = VBoolean("private_feeds"),
pref_local_js = VBoolean('local_js'),
pref_store_visits = VBoolean('store_visits'),
pref_show_adbox = VBoolean("show_adbox"),
pref_show_sponsors = VBoolean("show_sponsors"),
pref_show_sponsorships = VBoolean("show_sponsorships"),

View File

@@ -391,7 +391,7 @@ class LinkJsonTemplate(ThingJsonTemplate):
author_flair_css_class="author_flair_css_class",
author_flair_text="author_flair_text",
banned_by="banned_by",
clicked="clicked",
visited="visited",
distinguished="distinguished",
domain="domain",
downs="downvotes",

View File

@@ -116,9 +116,12 @@ def media_https_if_secure(url):
def js_config(extra_config=None):
logged = c.user_is_loggedin and c.user.name
gold = bool(logged and c.user.gold)
config = {
# is the user logged in?
"logged": c.user_is_loggedin and c.user.name,
"logged": logged,
# the subreddit's name (for posts)
"post_site": c.site.name if not c.default_sr else "",
# are we in an iframe?
@@ -127,6 +130,11 @@ def js_config(extra_config=None):
"modhash": c.modhash or False,
# the current rendering style
"renderstyle": c.render_style,
# they're welcome to try to override this in the DOM because we just
# disable the features server-side if applicable
'store_visits': gold and c.user.pref_store_visits,
# current domain
"cur_domain": get_domain(cname=c.frameless_cname, subreddit=False, no_www=True),
# where do ajax requests go?

View File

@@ -63,6 +63,7 @@ class Account(Thing):
pref_frame_commentspanel = False,
pref_newwindow = False,
pref_clickgadget = 5,
pref_store_visits = False,
pref_public_votes = False,
pref_hide_from_robots = False,
pref_research = False,

View File

@@ -206,13 +206,6 @@ class Link(Thing, Printable):
LinkSavesByAccount._unsave(user, self)
return self._unsomething(user, self._saved, 'save')
@classmethod
def _clicked(cls, user, link):
return cls._somethinged(Click, user, link, 'click')
def _click(self, user):
return self._something(Click, user, self._clicked, 'click')
@classmethod
def _hidden(cls, user, link):
return cls._somethinged(SaveHide, user, link, 'hide')
@@ -374,6 +367,9 @@ class Link(Thing, Printable):
pref_newwindow = user.pref_newwindow
cname = c.cname
site = c.site
now = datetime.now(g.tz)
saved = hidden = visited = {}
if user_is_admin:
# Checking if a domain's banned isn't even cheap
@@ -388,13 +384,14 @@ class Link(Thing, Printable):
try:
saved = LinkSavesByAccount.fast_query(user, wrapped)
hidden = LinkHidesByAccount.fast_query(user, wrapped)
except tdb_cassandra.TRANSIENT_EXCEPTIONS as e:
g.log.warning("Cassandra save/hide lookup failed: %r", e)
saved = hidden = {}
clicked = {}
else:
saved = hidden = clicked = {}
if user.gold and user.pref_store_visits:
visited = LinkVisitsByAccount.fast_query(user, wrapped)
except tdb_cassandra.TRANSIENT_EXCEPTIONS as e:
# saved or hidden or may have been done properly, so go ahead
# with what we do have
g.log.warning("Cassandra save/hide/visited lookup failed: %r", e)
for item in wrapped:
show_media = False
@@ -460,10 +457,10 @@ class Link(Thing, Printable):
if user_is_loggedin:
item.saved = (user, item) in saved
item.hidden = (user, item) in hidden
item.visited = (user, item) in visited
item.clicked = bool(clicked.get((user, item, 'click')))
else:
item.saved = item.hidden = item.clicked = False
item.saved = item.hidden = item.visited = False
item.num = None
item.permalink = item.make_permalink(item.subreddit)
@@ -569,7 +566,7 @@ class Link(Thing, Printable):
item.fresh = not any((item.likes != None,
item.saved,
item.clicked,
item.visited,
item.hidden,
item._deleted,
item._spam))
@@ -586,7 +583,8 @@ class Link(Thing, Printable):
item.author = DeletedUser()
item.as_deleted = True
item_age = datetime.now(g.tz) - item._date
item_age = now - item._date
if item_age.days > g.VOTE_AGE_LIMIT and item.promoted is None:
item.votable = False
else:
@@ -977,6 +975,7 @@ class Comment(Thing, Printable):
focal_comment = c.focal_comment
cname = c.cname
site = c.site
now = datetime.now(g.tz)
if user_is_loggedin:
gilded = [comment for comment in wrapped if comment.gildings > 0]
@@ -1031,7 +1030,7 @@ class Comment(Thing, Printable):
item.can_reply = False
if c.can_reply or (item.sr_id in can_reply_srs):
age = datetime.now(g.tz) - item._date
age = now - item._date
if item.link.promoted or age.days < g.REPLY_AGE_LIMIT:
item.can_reply = True
@@ -1534,8 +1533,6 @@ class Message(Thing, Printable):
return True
class SaveHide(Relation(Account, Link)): pass
class Click(Relation(Account, Link)): pass
class GildedCommentsByAccount(tdb_cassandra.DenormalizedRelation):
_use_db = True
@@ -1709,6 +1706,20 @@ class LinkHidesByAccount(_ThingHidesByAccount):
from r2.lib.db import queries
return [queries.get_hidden_links(user)]
class LinkVisitsByAccount(_SaveHideByAccount):
_use_db = True
_last_modified_name = 'Visit'
_views = []
_ttl = timedelta(days=7)
_write_consistency_level = tdb_cassandra.CL.ONE
@classmethod
def _visit(cls, user, things):
cls._savehide(user, things)
@classmethod
def _unvisit(cls, user, things):
cls._unsavehide(user, things)
class _ThingSavesBySubreddit(tdb_cassandra.View):
@classmethod

View File

@@ -316,6 +316,9 @@
${checkbox(_("show sponsorships"), "show_sponsorships")}
&#32;<span class="little gray">(${_("the 300x100 'sponsored by...' images that sometimes appear in sidebars")})</span>
<br/>
${checkbox(_("remember what links I've visited"), "store_visits")}
&#32;<span class="little gray">(${_("we'll remember and mark what links you've already read, even between computers")})</span>
<br/>
<br/>
${checkbox(_("highlight new comments"), "highlight_new_comments")}
&#32;<span class="little gray">