The 'share' link can now share with reddit users via PM.

From /r/ideasfortheadmins http://redd.it/z5d0y
This commit is contained in:
Roger Ostrander
2012-11-15 14:20:08 -08:00
parent 2efdb437fa
commit 1340e0c0ef
4 changed files with 116 additions and 15 deletions

View File

@@ -65,6 +65,7 @@ from r2.lib.search import SearchQuery
from r2.controllers.oauth2 import OAuth2ResourceController, require_oauth2_scope
from r2.lib.system_messages import notify_user_added
from r2.controllers.ipn import generate_blob
from r2.lib.template_helpers import add_sr, get_domain
from r2.models import wiki
from r2.lib.merge import ConflictException
@@ -1090,12 +1091,13 @@ class ApiController(RedditController, OAuth2ResourceController):
VRatelimit(rate_user = True, rate_ip = True,
prefix = "rate_share_"),
share_from = VLength('share_from', max_length = 100),
emails = ValidEmails("share_to"),
emails = ValidEmailsOrExistingUnames("share_to"),
reply_to = ValidEmails("replyto", num = 1),
message = VLength("message", max_length = 1000),
thing = VByName('parent'))
thing = VByName('parent'),
ip = ValidIP())
def POST_share(self, shareform, jquery, emails, thing, share_from, reply_to,
message):
message, ip):
# remove the ratelimit error if the user's karma is high
sr = thing.subreddit_slow
@@ -1123,6 +1125,7 @@ class ApiController(RedditController, OAuth2ResourceController):
elif shareform.has_errors("ratelimit", errors.RATELIMIT):
pass
else:
emails, users = emails
c.user.add_share_emails(emails)
c.user._commit()
link = jquery.things(thing._fullname)
@@ -1130,10 +1133,54 @@ class ApiController(RedditController, OAuth2ResourceController):
shareform.html("<div class='clearleft'></div>"
"<p class='error'>%s</p>" %
_("your link has been shared."))
# Set up the parts that are common between e-mail and PMs
urlparts = (get_domain(cname=c.cname, subreddit=False),
thing._id36)
url = "http://%s/tb/%s" % urlparts
if message:
message = message + "\n\n"
else:
message = ""
message = message + '\n%s\n\n%s\n\n' % (thing.title,url)
# Deliberately not translating this, as it'd be in the
# sender's language
if thing.num_comments:
count = ("There are currently %(num_comments)s comments on " +
"this link. You can view them here:")
if thing.num_comments == 1:
count = ("There is currently %(num_comments)s comment " +
"on this link. You can view it here:")
numcom = count % {'num_comments':thing.num_comments}
message = message + "%s\n\n" % numcom
else:
message = message + "You can leave a comment here:\n\n"
url = add_sr(thing.make_permalink_slow(), force_hostname=True)
message = message + url
# E-mail everyone
emailer.share(thing, emails, from_name = share_from or "",
body = message or "", reply_to = reply_to or "")
# Send the PMs
subject = "%s has shared a link with you!" % c.user.name
# Prepend this subject to the message - we're repeating ourselves
# because it looks very abrupt without it.
message = "%s\n\n%s" % (subject,message)
for target in users:
m, inbox_rel = Message._new(c.user, target, subject,
message, ip)
# Queue up this PM
amqp.add_item('new_message', m._fullname)
queries.new_message(m, inbox_rel)
#set the ratelimiter
if should_ratelimit:
VRatelimit.ratelimit(rate_user=True, rate_ip = True,

View File

@@ -1488,6 +1488,70 @@ class ValidEmails(Validator):
# return single email if one is expected, list otherwise
return list(emails)[0] if self.num == 1 else emails
class ValidEmailsOrExistingUnames(Validator):
"""Validates a list of mixed email addresses and usernames passed in
as a string, delineated by whitespace, ',' or ';'. Validates total
quantity too while we're at it. Returns a tuple of the form
(e-mail addresses, user account objects)"""
def __init__(self, param, num=20, **kw):
self.num = num
Validator.__init__(self, param=param, **kw)
def run(self, items):
# Use ValidEmails separator to break the list up
everything = set(ValidEmails.separator.findall(items) if items else [])
# Use ValidEmails regex to divide the list into e-mail and other
emails = set(e for e in everything if ValidEmails.email_re.match(e))
failures = everything - emails
# Run the rest of the validator against the e-mails list
ve = ValidEmails(self.param, self.num)
if len(emails) > 0:
ve.run(", ".join(emails))
# ValidEmails will add to c.errors for us, so do nothing if that fails
# Elsewise, on with the users
if not ve.has_errors:
users = set() # set of accounts
validusers = set() # set of usernames to subtract from failures
# Now steal from VExistingUname:
for uname in failures:
check = uname
if re.match('/u/', uname):
check = check[3:]
veu = VExistingUname(check)
account = veu.run(check)
if account:
validusers.add(uname)
users.add(account)
# We're fine if all our failures turned out to be valid users
if len(users) == len(failures):
# ValidEmails checked to see if there were too many addresses,
# check to see if there's enough left-over space for users
remaining = self.num - len(emails)
if len(users) > remaining:
if self.num == 1:
# We only wanted one, and we got it as an e-mail,
# so complain.
self.set_error(errors.BAD_EMAILS,
{"emails": '"%s"' % items})
else:
# Too many total
self.set_error(errors.TOO_MANY_EMAILS,
{"num": self.num})
elif len(users) + len(emails) == 0:
self.set_error(errors.NO_EMAILS)
else:
# It's all good!
return (emails, users)
else:
failures = failures - validusers
self.set_error(errors.BAD_EMAILS,
{'emails': ', '.join(failures)})
class VCnameDomain(Validator):
domain_re = re.compile(r'\A([\w\-_]+\.)+[\w]+\Z')

View File

@@ -21,18 +21,9 @@
###############################################################################
<%! from r2.lib.template_helpers import get_domain%>
%if not thing.body:
${thing.username} from http://${get_domain(cname = c.cname, subreddit = False)}/ has shared a link with you.
%else:
${thing.body}
%endif
"${thing.link.title}"
http://${get_domain(cname = c.cname, subreddit = False)}/tb/${thing.link._id36}
<% from r2.lib.strings import strings, plurals %>${ungettext("There is currently %(num_comments)s on this link. You can view it here:", "There are currently %(num_comments)s on this link. You can view them here:", thing.link.num_comments) % dict(num_comments = strings.number_label % dict(num=thing.link.num_comments, thing=plurals.N_comments(thing.link.num_comments)))}
<% from r2.lib.template_helpers import add_sr %>${add_sr(thing.link.make_permalink_slow(), force_hostname = True)}
___
If you would not like to receive emails from reddit.com in the future, visit http://${g.domain}/mail/optout?x=${thing.msg_hash}

View File

@@ -98,7 +98,6 @@
<td>
<textarea id="message_${thing.link_name}"
name="message" rows="4" cols="40">
${_("%(user)s from http://%(site)s/ has shared a link with you.") % dict(user = c.user.name, site=c.site.domain if c.cname and hasattr(c.site, 'domain') else g.domain)}
</textarea>
</td>
<td class="message-errors">