Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Track subreddit participation directly
Browse files Browse the repository at this point in the history
The previous method of determining whether a user had interacted with a
particular subreddit (to decide whether to send them a "you've been
banned" message or not) was by checking to see whether they had any
karma (positive or negative) in the subreddit, or if they were currently
subscribed to it. This missed a fair number of cases, most significantly
that making self-posts would not count as having interacted with the
subreddit, since they have no effect on karma.

This commit uses a DenormalizedRelation to track whether a user has
interacted with the subreddit (actually *when* they last interacted with
it, though that data is currently unused). It adds one new type of
action that is considered interaction - sending a modmail to the
subreddit.  It also removes the error/warning from the ban page about
trying to send a ban message to someone that has never interacted with
the subreddit, since that should no longer really be a concern.
  • Loading branch information
Deimos committed May 26, 2015
1 parent e07ec85 commit 495d761
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 31 deletions.
9 changes: 2 additions & 7 deletions r2/r2/controllers/api.py
Expand Up @@ -1041,13 +1041,6 @@ def POST_friend(self, form, jquery, friend,
if type == "banned":
if form.has_errors("ban_message", errors.TOO_LONG):
return

# don't let them ban with a custom message if the user won't
# actually be messaged
if ban_message and not friend.has_interacted_with(container):
c.errors.add(errors.USER_BAN_NO_MESSAGE, field="ban_message")
form.set_error(errors.USER_BAN_NO_MESSAGE, "ban_message")
return
else:
ban_message = None

Expand Down Expand Up @@ -3365,6 +3358,8 @@ def POST_subscribe(self, action, sr):
Subreddit.subscribe_defaults(c.user)

if action == "sub":
SubredditParticipationByAccount.mark_participated(c.user, sr)

if sr.add_subscriber(c.user):
sr._incr('_ups', 1)
else:
Expand Down
1 change: 1 addition & 0 deletions r2/r2/lib/db/tdb_cassandra.py
Expand Up @@ -34,6 +34,7 @@
from pycassa.system_manager import (
ASCII_TYPE,
COUNTER_COLUMN_TYPE,
DATE_TYPE,
INT_TYPE,
SystemManager,
TIME_UUID_TYPE,
Expand Down
1 change: 0 additions & 1 deletion r2/r2/lib/errors.py
Expand Up @@ -157,7 +157,6 @@
('SCRAPER_ERROR', _("unable to scrape provided url")),
('NO_SR_TO_SR_MESSAGE', _("can't send a message from a subreddit to another subreddit")),
('USER_BLOCKED_MESSAGE', _("can't send message to that user")),
('USER_BAN_NO_MESSAGE', _("that user will not be sent a ban notification, remove note to be able to ban")),
('ADMIN_REQUIRED', _("you must be in admin mode for this")),
('CANT_CONVERT_TO_GOLD_ONLY', _("to convert an existing subreddit to gold only, send a message to %(admin_modmail)s")
% dict(admin_modmail=g.admin_message_acct)),
Expand Down
31 changes: 22 additions & 9 deletions r2/r2/models/account.py
Expand Up @@ -165,17 +165,12 @@ def __ne__(self, other):
return not self.__eq__(other)

def has_interacted_with(self, sr):
if not sr:
try:
r = SubredditParticipationByAccount.fast_query(self, [sr])
except tdb_cassandra.NotFound:
return False

for type in ('link', 'comment'):
if hasattr(self, "%s_%s_karma" % (sr.name, type)):
return True

if sr.is_subscriber(self):
return True

return False
return (self, sr) in r

def karma(self, kind, sr = None):
suffix = '_' + kind + '_karma'
Expand Down Expand Up @@ -1067,3 +1062,21 @@ def get_accounts(cls, email_address):
return []
account_id36s = cls.get_time_sorted_columns(canonical).keys()
return Account._byID36(account_id36s, data=True, return_dict=False)


class SubredditParticipationByAccount(tdb_cassandra.DenormalizedRelation):
_use_db = True
_write_last_modified = False
_views = []
_extra_schema_creation_args = {
"key_validation_class": tdb_cassandra.ASCII_TYPE,
"default_validation_class": tdb_cassandra.DATE_TYPE,
}

@classmethod
def value_for(cls, thing1, thing2):
return datetime.now(g.tz)

@classmethod
def mark_participated(cls, account, subreddit):
cls.create(account, [subreddit])
13 changes: 12 additions & 1 deletion r2/r2/models/link.py
Expand Up @@ -32,7 +32,12 @@
tup,
UrlParser,
)
from account import Account, DeletedUser, BlockedSubredditsByAccount
from account import (
Account,
BlockedSubredditsByAccount,
DeletedUser,
SubredditParticipationByAccount,
)
from subreddit import DefaultSR, DomainSR, Subreddit
from printable import Printable
from r2.config import extensions
Expand Down Expand Up @@ -210,6 +215,7 @@ def _submit(cls, title, url, author, sr, ip, spam=False, sendreplies=True):
l._commit()
l.set_url_cache()
LinksByAccount.add_link(author, l)
SubredditParticipationByAccount.mark_participated(author, sr)
if author._spam:
g.stats.simple_event('spam.autoremove.link')
admintools.spam(l, banner='banned user')
Expand Down Expand Up @@ -1000,6 +1006,8 @@ def _new(cls, author, link, parent, body, ip):
link.update_search_index(boost_only=True)

CommentsByAccount.add_comment(author, c)
SubredditParticipationByAccount.mark_participated(
author, c.subreddit_slow)

def should_send():
# don't send the message to author if replying to own comment
Expand Down Expand Up @@ -1651,6 +1659,9 @@ def _new(cls, author, to, subject, body, ip, parent=None, sr=None,
if sr_id and not sr:
sr = Subreddit._byID(sr_id)

if to_subreddit:
SubredditParticipationByAccount.mark_participated(author, sr)

inbox_rel = []

inbox_hook = hooks.get_hook("message.skip_inbox")
Expand Down
7 changes: 0 additions & 7 deletions r2/r2/public/static/css/reddit.less
Expand Up @@ -8211,13 +8211,6 @@ form#banned textarea {
margin-left: 0;
}

div.usertable .note {
color: #808080;
font-size: 0.8em;
white-space: normal;
margin-bottom: 10px;
}

.gold-accent h1,
.gold-accent th {
color: #6a4d00;
Expand Down
6 changes: 0 additions & 6 deletions r2/r2/templates/userlisting.html
Expand Up @@ -36,11 +36,6 @@ <h1>${title}</h1>
<input type="hidden" name="action" value="add">
<input type="hidden" name="container" value="${container_name}">
<input type="hidden" name="type" value="${add_type}">
%if add_type == "banned":
<div class="note">
${_("note: the banned user will only receive a message notifying them of their ban if they are subscribed to the subreddit or have previously gained or lost any karma (either link or comment) in the subreddit.")}
</div>
%endif
%if add_type in ("banned", "wikibanned"):
<label for="name">${_('who to ban?')} &nbsp;</label>
<input type="text" class="friend-name" name="name" id="name">
Expand Down Expand Up @@ -75,7 +70,6 @@ <h1>${title}</h1>
${error_field("USER_DOESNT_EXIST", "name")}
${error_field("ALREADY_MODERATOR", "name")}
${error_field("BANNED_FROM_SUBREDDIT", "name")}
${error_field("USER_BAN_NO_MESSAGE", "ban_message")}
%if caller:
${caller.body()}
%endif
Expand Down

0 comments on commit 495d761

Please sign in to comment.