def send_system_message(user, subject, body, system_user=None, distinguished='admin', repliable=False, add_to_sent=True, author=None): from r2.lib.db import queries if system_user is None: system_user = Account.system_user() if not system_user: g.log.warning("Can't send system message " "- invalid system_user or g.system_user setting") return if not author: author = system_user item, inbox_rel = Message._new(author, user, subject, body, ip='0.0.0.0') item.distinguished = distinguished item.repliable = repliable item.display_author = system_user._id item._commit() try: queries.new_message(item, inbox_rel, add_to_sent=add_to_sent) except MemcachedError: raise MessageError('reddit_inbox')
def send_system_message(user, subject, body, system_user=None, distinguished='admin', repliable=False, add_to_sent=True, author=None, signed=False): from r2.lib.db import queries if system_user is None: system_user = Account.system_user() if not system_user: g.log.warning("Can't send system message " "- invalid system_user or g.system_user setting") return if not author: author = system_user item, inbox_rel = Message._new(author, user, subject, body, ip='0.0.0.0') item.distinguished = distinguished item.repliable = repliable item.display_author = system_user._id item.signed = signed item._commit() try: queries.new_message(item, inbox_rel, add_to_sent=add_to_sent) except MemcachedError: raise MessageError('reddit_inbox')
def create_sr(self): subreddit = None print "attempting to create sr for %s" % self.name for name in self._generate_sr_name(): try: subreddit = Subreddit._new( name=name, title=self.name[:100], author_id=Account.system_user()._id, ip='0.0.0.0', type='private', ) break except SubredditExists: print 'subreddit %s already exists' % name continue except ValueError: print 'bad subreddit name, giving up: %s' % name return subreddit else: print "gave up attempting to create sr for %s" % self.name return subreddit self.subreddit_name = subreddit.name self._commit() return subreddit
def POST_authorize(self, authorize, client, redirect_uri, scope, state, duration, response_type): """Endpoint for OAuth2 authorization.""" self._check_employee_grants(client, scope) self._check_redirect_uri(client, redirect_uri) self._check_response_type_and_scope(response_type, scope) self._check_client_type_and_duration(response_type, client, duration) if c.errors: return self._error_response(state, redirect_uri, as_fragment=(response_type == "token")) if response_type == "code": code = OAuth2AuthorizationCode._new(client._id, redirect_uri, c.user._id36, scope, duration == "permanent") resp = {"code": code._id, "state": state} final_redirect = _update_redirect_uri(redirect_uri, resp) g.stats.simple_event('oauth2.POST_authorize.authorization_code_create') elif response_type == "token": token = OAuth2AccessToken._new(client._id, c.user._id36, scope) token_data = OAuth2AccessController._make_token_dict(token) token_data["state"] = state final_redirect = _update_redirect_uri(redirect_uri, token_data, as_fragment=True) g.stats.simple_event('oauth2.POST_authorize.access_token_create') # If this is the first time the user is logging in with an official # mobile app, gild them if (g.live_config.get('mobile_gild_first_login') and not c.user.has_used_mobile_app and client._id in g.mobile_auth_gild_clients): buyer = Account.system_user() admintools.adjust_gold_expiration( c.user, days=g.mobile_auth_gild_time) create_gift_gold( buyer._id, c.user._id, g.mobile_auth_gild_time, datetime.now(g.tz), signed=True, note='first_mobile_auth') subject = 'Let there be gold! Reddit just sent you Reddit gold!' message = ( "Thank you for using the Reddit mobile app! As a thank you " "for logging in during launch week, you've been gifted %s of " "Reddit Gold.\n\n" "Reddit Gold is Reddit's premium membership program, which " "grants you: \n" "An ads-free experience in Reddit's mobile apps, and\n" "Extra site features on desktop\n\n" "Discuss and get help on the features and perks at " "r/goldbenefits." ) % g.mobile_auth_gild_message message += '\n\n' + strings.gold_benefits_msg send_system_message(c.user, subject, message, add_to_sent=False) c.user.has_used_mobile_app = True c.user._commit() return self.redirect(final_redirect, code=302)
def notify_user_added(rel_type, author, user, target, message=None): msgs = user_added_messages.get(rel_type) if not msgs: return srname = target.path.rstrip("/") d = { "url": srname, "title": "%s: %s" % (srname, target.title), "author": "/u/" + author.name, "user": "******" + user.name, } if "pm" in msgs and author != user: subject = msgs["pm"]["subject"] % d msg = msgs["pm"]["msg"] % d if rel_type == "banned" and not user.has_interacted_with(target): return if rel_type == "banned" and message: msg += "\n\n" + N_("note from the moderators:\n\n\"%(message)s\"") msg %= {'message': message} if rel_type in ("banned", "moderator_invite"): # send the message from the subreddit item, inbox_rel = Message._new(author, user, subject, msg, request.ip, sr=target, from_sr=True) else: item, inbox_rel = Message._new(author, user, subject, msg, request.ip) queries.new_message(item, inbox_rel) if "modmail" in msgs: subject = msgs["modmail"]["subject"] % d msg = msgs["modmail"]["msg"] % d if rel_type == "moderator_invite": modmail_author = Account.system_user() else: modmail_author = author item, inbox_rel = Message._new(modmail_author, target, subject, msg, request.ip, sr=target) queries.new_message(item, inbox_rel)
def POST_authorize(self, authorize, client, redirect_uri, scope, state, duration, response_type): """Endpoint for OAuth2 authorization.""" self._check_employee_grants(client, scope) if response_type == "token" and client.is_confidential(): # Prevent "confidential" clients from distributing tokens # in a non-confidential manner c.errors.add((errors.OAUTH2_INVALID_CLIENT, "client_id")) if response_type == "token" and duration != "temporary": # implicit grant -> No refresh tokens allowed c.errors.add((errors.INVALID_OPTION, "duration")) self._check_redirect_uri(client, redirect_uri) if c.errors: return self._error_response(state, redirect_uri, as_fragment=(response_type == "token")) if response_type == "code": code = OAuth2AuthorizationCode._new(client._id, redirect_uri, c.user._id36, scope, duration == "permanent") resp = {"code": code._id, "state": state} final_redirect = _update_redirect_uri(redirect_uri, resp) elif response_type == "token": token = OAuth2AccessToken._new(client._id, c.user._id36, scope) token_data = OAuth2AccessController._make_token_dict(token) token_data["state"] = state final_redirect = _update_redirect_uri(redirect_uri, token_data, as_fragment=True) # If this is the first time the user is logging in with an official # mobile app, gild them if (g.live_config.get('mobile_gild_first_login') and not c.user.has_used_mobile_app and client._id in g.mobile_auth_gild_clients): buyer = Account.system_user() admintools.adjust_gold_expiration( c.user, days=g.mobile_auth_gild_time) create_gift_gold( buyer._id, c.user._id, g.mobile_auth_gild_time, datetime.now(g.tz), signed=True, note='first_mobile_auth') subject = 'Let there be gold! %s just sent you reddit gold!' % ( buyer.name) message = "Thank you for using the reddit mobile app! For your "\ "participation, you've been gifted %s of reddit gold." % ( g.mobile_auth_gild_message) message += '\n\n' + strings.gold_benefits_msg send_system_message(c.user, subject, message, add_to_sent=False) c.user.has_used_mobile_app = True c.user._commit() return self.redirect(final_redirect, code=302)
def notify_user_added(rel_type, author, user, target): msgs = user_added_messages.get(rel_type) if not msgs: return srname = target.path.rstrip("/") d = { "url": srname, "title": "%s: %s" % (srname, target.title), "author": "/u/" + author.name, "user": "******" + user.name, } if "pm" in msgs and author != user: subject = msgs["pm"]["subject"] % d msg = msgs["pm"]["msg"] % d if rel_type in ("moderator_invite", "contributor"): # send the message from the subreddit item, inbox_rel = Message._new(author, user, subject, msg, request.ip, sr=target, from_sr=True, can_send_email=False) else: item, inbox_rel = Message._new(author, user, subject, msg, request.ip, can_send_email=False) queries.new_message(item, inbox_rel, update_modmail=False) if "modmail" in msgs: subject = msgs["modmail"]["subject"] % d msg = msgs["modmail"]["msg"] % d if rel_type == "moderator_invite": modmail_author = Account.system_user() else: modmail_author = author item, inbox_rel = Message._new(modmail_author, target, subject, msg, request.ip, sr=target) queries.new_message(item, inbox_rel)
def notify_user_added(rel_type, author, user, target): msgs = user_added_messages.get(rel_type) if not msgs: return srname = target.path.rstrip("/") d = { "url": srname, "title": "%s: %s" % (srname, target.title), "author": "/u/" + author.name, "user": "******" + user.name, } if "pm" in msgs and author != user: subject = msgs["pm"]["subject"] % d msg = msgs["pm"]["msg"] % d if rel_type in ("moderator_invite", "contributor"): # send the message from the subreddit item, inbox_rel = Message._new( author, user, subject, msg, request.ip, sr=target, from_sr=True, can_send_email=False, is_auto_modmail=True) else: item, inbox_rel = Message._new( author, user, subject, msg, request.ip, can_send_email=False) queries.new_message(item, inbox_rel, update_modmail=False) if "modmail" in msgs: subject = msgs["modmail"]["subject"] % d msg = msgs["modmail"]["msg"] % d if rel_type == "moderator_invite": # Don't send the separate moderator invite message from the # system user to new modmail, since the one sent to the invitee # will already show up in there. # TODO: when new modmail is fully deployed, the "modmail" dict # should be completely removed from the moderator_invite section # of user_added_messages, and this check removed. if feature.is_enabled('new_modmail', subreddit=target.name): return modmail_author = Account.system_user() else: modmail_author = author item, inbox_rel = Message._new(modmail_author, target, subject, msg, request.ip, sr=target, is_auto_modmail=True) queries.new_message(item, inbox_rel)
def send_system_message(user, subject, body): from r2.lib.db import queries system_user = Account.system_user() if not system_user: g.log.warning("g.system_user isn't set properly. Can't send system message.") return item, inbox_rel = Message._new(system_user, user, subject, body, ip='0.0.0.0') item.distinguished = 'admin' item.repliable = False item._commit() queries.new_message(item, inbox_rel)
def notify_user_added(rel_type, author, user, target, message=None): msgs = user_added_messages.get(rel_type) if not msgs: return srname = target.path.rstrip("/") d = { "url": srname, "title": "%s: %s" % (srname, target.title), "author": "/u/" + author.name, "user": "******" + user.name, } if "pm" in msgs and author != user: subject = msgs["pm"]["subject"] % d msg = msgs["pm"]["msg"] % d if rel_type == "banned" and not user.has_interacted_with(target): return if rel_type == "banned" and message: msg += "\n\n" + N_("note from the moderators:\n\n\"%(message)s\"") msg %= {'message': message} if rel_type in ("banned", "moderator_invite"): # send the message from the subreddit item, inbox_rel = Message._new(author, user, subject, msg, request.ip, sr=target, from_sr=True) else: item, inbox_rel = Message._new(author, user, subject, msg, request.ip) queries.new_message(item, inbox_rel, update_modmail=False) if "modmail" in msgs: subject = msgs["modmail"]["subject"] % d msg = msgs["modmail"]["msg"] % d if rel_type == "moderator_invite": modmail_author = Account.system_user() else: modmail_author = author item, inbox_rel = Message._new(modmail_author, target, subject, msg, request.ip, sr=target) queries.new_message(item, inbox_rel, update_modmail=False)
def send_system_message(user, subject, body, system_user=None, distinguished="admin", repliable=False): from r2.lib.db import queries if system_user is None: system_user = Account.system_user() if not system_user: g.log.warning("Can't send system message " "- invalid system_user or g.system_user setting") return item, inbox_rel = Message._new(system_user, user, subject, body, ip="0.0.0.0") item.distinguished = distinguished item.repliable = repliable item._commit() try: queries.new_message(item, inbox_rel) except MemcachedError: raise MessageError("reddit_inbox")
def notify_user_added(rel_type, author, user, target): msgs = user_added_messages.get(rel_type) if not msgs: return srname = target.path.rstrip("/") d = { "url": srname, "title": "%s: %s" % (srname, target.title), "author": "/u/" + author.name, "user": "******" + user.name, } if "pm" in msgs and author != user: subject = msgs["pm"]["subject"] % d msg = msgs["pm"]["msg"] % d if rel_type in ("moderator_invite", "contributor"): # send the message from the subreddit item, inbox_rel = Message._new( author, user, subject, msg, request.ip, sr=target, from_sr=True, can_send_email=False) else: item, inbox_rel = Message._new( author, user, subject, msg, request.ip, can_send_email=False) queries.new_message(item, inbox_rel, update_modmail=False) if "modmail" in msgs: subject = msgs["modmail"]["subject"] % d msg = msgs["modmail"]["msg"] % d if rel_type == "moderator_invite": modmail_author = Account.system_user() else: modmail_author = author item, inbox_rel = Message._new(modmail_author, target, subject, msg, request.ip, sr=target) queries.new_message(item, inbox_rel)
def POST_authorize(self, authorize, client, redirect_uri, scope, state, duration, response_type): """Endpoint for OAuth2 authorization.""" self._check_employee_grants(client, scope) self._check_redirect_uri(client, redirect_uri) self._check_response_type_and_scope(response_type, scope) self._check_client_type_and_duration(response_type, client, duration) if c.errors: return self._error_response(state, redirect_uri, as_fragment=(response_type == "token")) if response_type == "code": code = OAuth2AuthorizationCode._new(client._id, redirect_uri, c.user._id36, scope, duration == "permanent") resp = {"code": code._id, "state": state} final_redirect = _update_redirect_uri(redirect_uri, resp) g.stats.simple_event('oauth2.POST_authorize.authorization_code_create') elif response_type == "token": device_id = get_device_id(client) token = OAuth2AccessToken._new( client_id=client._id, user_id=c.user._id36, scope=scope, device_id=device_id, ) resp = OAuth2AccessController._make_new_token_response(token) resp["state"] = state final_redirect = _update_redirect_uri(redirect_uri, resp, as_fragment=True) g.stats.simple_event('oauth2.POST_authorize.access_token_create') # If this is the first time the user is logging in with an official # mobile app, gild them if (g.live_config.get('mobile_gild_first_login') and not c.user.has_used_mobile_app and client._id in g.mobile_auth_gild_clients): buyer = Account.system_user() admintools.adjust_gold_expiration( c.user, days=g.mobile_auth_gild_time) create_gift_gold( buyer._id, c.user._id, g.mobile_auth_gild_time, datetime.now(g.tz), signed=True, note='first_mobile_auth') subject = 'Let there be gold! Reddit just sent you Reddit gold!' message = ( "Thank you for using the Reddit mobile app! As a thank you " "for logging in during launch week, you've been gifted %s of " "Reddit Gold.\n\n" "Reddit Gold is Reddit's premium membership program, which " "grants you: \n" "An ads-free experience in Reddit's mobile apps, and\n" "Extra site features on desktop\n\n" "Discuss and get help on the features and perks at " "r/goldbenefits." ) % g.mobile_auth_gild_message message += '\n\n' + strings.gold_benefits_msg send_system_message(c.user, subject, message, add_to_sent=False) c.user.has_used_mobile_app = True c.user._commit() return self.redirect(final_redirect, code=302)
def modmail_event(self, message, request=None, context=None): """Create a 'modmail' event for event-collector. message: An r2.models.Message object request: pylons.request of the request that created the message context: pylons.tmpl_context of the request that created the message """ from r2.models import Account, Message sender = message.author_slow sr = message.subreddit_slow sender_is_moderator = sr.is_moderator_with_perms(sender, "mail") if message.first_message: first_message = Message._byID(message.first_message, data=True) else: first_message = message event = EventV2( topic="message_events", event_type="ss.send_message", time=message._date, request=request, context=context, data={ # set these manually rather than allowing them to be set from # the request context because the loggedin user might not # be the message sender "user_id": sender._id, "user_name": sender.name, }, ) if sender == Account.system_user(): sender_type = "automated" elif sender_is_moderator: sender_type = "moderator" else: sender_type = "user" event.add("sender_type", sender_type) event.add("sr_id", sr._id) event.add("sr_name", sr.name) event.add("message_id", message._id) event.add("message_fullname", message._fullname) event.add("first_message_id", first_message._id) event.add("first_message_fullname", first_message._fullname) if request and request.POST.get("source", None): source = request.POST["source"] if source in {"compose", "permalink", "modmail", "usermail"}: event.add("page", source) if message.sent_via_email: event.add("is_third_party", True) event.add("third_party_metadata", "mailgun") if not message.to_id: target = sr else: target = Account._byID(message.to_id, data=True) event.add_target_fields(target) self.save_event(event)
def POST_zendeskreply(self): request_body = request.POST recipient = request_body["recipient"] sender_email = request_body["sender"] from_ = request_body["from"] subject = request_body["subject"] body_plain = request_body["body-plain"] stripped_text = request_body["stripped-text"] stripped_signature = request_body["stripped-signature"] timestamp = request_body["timestamp"] token = request_body["token"] signature = request_body["signature"] email_id = request_body["Message-Id"] if not validate_mailgun_webhook(timestamp, token, signature): # per Mailgun docs send a 406 so the message won't be retried abort(406, "invalid signature") message_id36 = parse_and_validate_reply_to_address(recipient) if not message_id36: # per Mailgun docs send a 406 so the message won't be retried abort(406, "invalid message") parent = Message._byID36(message_id36, data=True) to = Account._byID(parent.author_id, data=True) sr = Subreddit._byID(parent.sr_id, data=True) body = self.get_snipped_body(stripped_text, stripped_signature) try: markdown_souptest(body) except SoupError: g.log.warning("bad markdown in modmail email: %s", body) abort(406, "invalid body") if parent.get_muted_user_in_conversation(): queue_blocked_muted_email(sr, parent, sender_email, email_id) return # keep the subject consistent message_subject = parent.subject if not message_subject.startswith("re: "): message_subject = "re: " + message_subject # from_ is like '"NAME (GROUP)" <*****@*****.**>' match = re.search("\"(?P<name>\w+) [\w ()]*\"", from_) from_sr = True author = Account.system_user() if match and match.group("name") in g.live_config['modmail_account_map']: zendesk_name = match.group("name") moderator_name = g.live_config['modmail_account_map'][zendesk_name] moderator = Account._by_name(moderator_name) if sr.is_moderator_with_perms(moderator, "mail"): author = moderator from_sr = False message, inbox_rel = Message._new( author=author, to=to, subject=message_subject, body=body, ip='0.0.0.0', parent=parent, sr=sr, from_sr=from_sr, can_send_email=False, sent_via_email=True, email_id=email_id, ) message._commit() queries.new_message(message, inbox_rel) g.stats.simple_event("mailgun.incoming.success") g.stats.simple_event("modmail_email.incoming_email")
def message_event(self, message, request=None, context=None): """Create a 'message' event for event-collector. message: An r2.models.Message object request: pylons.request of the request that created the message context: pylons.tmpl_context of the request that created the message """ from r2.models import Account, Message sender = message.author_slow if message.first_message: first_message = Message._byID(message.first_message, data=True) else: first_message = message event = Event( topic="message_events", event_type="ss.send_message", time=message._date, request=request, context=context, data={ # set these manually rather than allowing them to be set from # the request context because the loggedin user might not # be the message sender "user_id": sender._id, "user_name": sender.name, }, ) if sender == Account.system_user(): sender_type = "automated" else: sender_type = "user" event.add("sender_type", sender_type) event.add("message_kind", "message") event.add("message_id", message._id) event.add("message_fullname", message._fullname) event.add_text("message_body", message.body) event.add_text("message_subject", message.subject) event.add("first_message_id", first_message._id) event.add("first_message_fullname", first_message._fullname) if request and request.POST.get("source", None): source = request.POST["source"] if source in {"compose", "permalink", "usermail"}: event.add("page", source) if message.sent_via_email: event.add("is_third_party", True) event.add("third_party_metadata", "mailgun") target = Account._byID(message.to_id, data=True) event.add_target_fields(target) self.save_event(event)
def _get_user(): return Account.system_user()
def POST_zendeskreply(self): request_body = request.POST recipient = request_body["recipient"] sender_email = request_body["sender"] from_ = request_body["from"] subject = request_body["subject"] body_plain = request_body["body-plain"] stripped_text = request_body["stripped-text"] stripped_signature = request_body["stripped-signature"] timestamp = request_body["timestamp"] token = request_body["token"] signature = request_body["signature"] email_id = request_body["Message-Id"] if not validate_mailgun_webhook(timestamp, token, signature): # per Mailgun docs send a 406 so the message won't be retried abort(406, "invalid signature") message_id36 = parse_and_validate_reply_to_address(recipient) if not message_id36: # per Mailgun docs send a 406 so the message won't be retried abort(406, "invalid message") parent = Message._byID36(message_id36, data=True) to = Account._byID(parent.author_id, data=True) sr = Subreddit._byID(parent.sr_id, data=True) body = self.get_snipped_body(stripped_text, stripped_signature) try: markdown_souptest(body) except SoupError: g.log.warning("bad markdown in modmail email: %s", body) abort(406, "invalid body") if parent.get_muted_user_in_conversation(): queue_blocked_muted_email(sr, parent, sender_email, email_id) return # keep the subject consistent message_subject = parent.subject if not message_subject.startswith("re: "): message_subject = "re: " + message_subject # from_ is like '"NAME (GROUP)" <*****@*****.**>' match = re.search("\"(?P<name>\w+) [\w ()]*\"", from_) from_sr = True author = Account.system_user() if match and match.group( "name") in g.live_config['modmail_account_map']: zendesk_name = match.group("name") moderator_name = g.live_config['modmail_account_map'][zendesk_name] moderator = Account._by_name(moderator_name) if sr.is_moderator_with_perms(moderator, "mail"): author = moderator from_sr = False message, inbox_rel = Message._new( author=author, to=to, subject=message_subject, body=body, ip='0.0.0.0', parent=parent, sr=sr, from_sr=from_sr, can_send_email=False, sent_via_email=True, email_id=email_id, ) message._commit() queries.new_message(message, inbox_rel) g.stats.simple_event("mailgun.incoming.success") g.stats.simple_event("modmail_email.incoming_email")
def notify_user_added(rel_type, author, user, target): msgs = user_added_messages.get(rel_type) if not msgs: return srname = target.path.rstrip("/") d = { "url": srname, "title": "%s: %s" % (srname, target.title), "author": "/u/" + author.name, "user": "******" + user.name, } if "pm" in msgs and author != user: subject = msgs["pm"]["subject"] % d msg = msgs["pm"]["msg"] % d if rel_type in ("moderator_invite", "contributor"): # send the message from the subreddit item, inbox_rel = Message._new(author, user, subject, msg, request.ip, sr=target, from_sr=True, can_send_email=False, is_auto_modmail=True) else: item, inbox_rel = Message._new(author, user, subject, msg, request.ip, can_send_email=False) queries.new_message(item, inbox_rel, update_modmail=False) if "modmail" in msgs: subject = msgs["modmail"]["subject"] % d msg = msgs["modmail"]["msg"] % d if rel_type == "moderator_invite": # Don't send the separate moderator invite message from the # system user to new modmail, since the one sent to the invitee # will already show up in there. # TODO: when new modmail is fully deployed, the "modmail" dict # should be completely removed from the moderator_invite section # of user_added_messages, and this check removed. if feature.is_enabled('new_modmail', subreddit=target.name): return modmail_author = Account.system_user() else: modmail_author = author item, inbox_rel = Message._new(modmail_author, target, subject, msg, request.ip, sr=target, is_auto_modmail=True) queries.new_message(item, inbox_rel)