mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-04-27 03:00:12 -04:00
Allow multiple messages in a single request to be marked as (un)read.
This commit is contained in:
committed by
Keith Mitchell
parent
619e158584
commit
a18e5e0e22
@@ -56,6 +56,7 @@ from r2.lib.filters import safemarkdown
|
||||
from r2.lib.scraper import str_to_image
|
||||
|
||||
import csv
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
from md5 import md5
|
||||
import urllib
|
||||
@@ -1511,29 +1512,43 @@ class ApiController(RedditController):
|
||||
def POST_uncollapse_message(self, things):
|
||||
self.collapse_handler(things, False)
|
||||
|
||||
def unread_handler(self, thing, unread):
|
||||
if not thing:
|
||||
return
|
||||
# if the message has a recipient, try validating that
|
||||
# desitination first (as it is cheaper and more common)
|
||||
queries.set_unread(thing, c.user, unread)
|
||||
# if the message is for a subreddit, check that next
|
||||
if hasattr(thing, "sr_id"):
|
||||
sr = thing.subreddit_slow
|
||||
if sr and sr.is_moderator(c.user):
|
||||
queries.set_unread(thing, sr, unread)
|
||||
def unread_handler(self, things, unread):
|
||||
if not things:
|
||||
if (errors.TOO_MANY_THING_IDS, 'id') in c.errors:
|
||||
return abort(413)
|
||||
else:
|
||||
return abort(400)
|
||||
|
||||
thing_groups = defaultdict(list)
|
||||
# Group things by subreddit or type
|
||||
for thing in things:
|
||||
if isinstance(thing, Message):
|
||||
if hasattr(thing, 'sr_id') and thing.sr_id:
|
||||
thing_groups[thing.sr_id].append(thing)
|
||||
else:
|
||||
thing_groups['Message'].append(thing)
|
||||
else:
|
||||
thing_groups['Comment'].append(thing)
|
||||
|
||||
# Batch set items as unread
|
||||
for sr_id, things in thing_groups.items():
|
||||
if sr_id not in ('Comment', 'Message'):
|
||||
queries.set_unread(things, things[0].subreddit_slow, unread)
|
||||
else:
|
||||
queries.set_unread(things, c.user, unread)
|
||||
|
||||
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
thing = VByName('id'))
|
||||
def POST_unread_message(self, thing):
|
||||
self.unread_handler(thing, True)
|
||||
things = VByName('id', multiple=True, limit=25))
|
||||
def POST_unread_message(self, things):
|
||||
self.unread_handler(things, True)
|
||||
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
thing = VByName('id'))
|
||||
def POST_read_message(self, thing):
|
||||
self.unread_handler(thing, False)
|
||||
things = VByName('id', multiple=True, limit=25))
|
||||
def POST_read_message(self, things):
|
||||
self.unread_handler(things, False)
|
||||
|
||||
@noresponse(VUser(),
|
||||
VModhash(),
|
||||
|
||||
@@ -34,6 +34,7 @@ error_list = dict((
|
||||
('USERNAME_TAKEN_DEL', _('that username is taken by a deleted account')),
|
||||
('USER_BLOCKED', _("you can't send to a user that you have blocked")),
|
||||
('NO_THING_ID', _('id not specified')),
|
||||
('TOO_MANY_THING_IDS', _('you provided too many ids')),
|
||||
('NOT_AUTHOR', _("you can't do that")),
|
||||
('NOT_USER', _("you are not logged in as that user")),
|
||||
('DELETED_LINK', _('the link you are commenting on has been deleted')),
|
||||
|
||||
@@ -540,10 +540,14 @@ def fullname_regex(thing_cls = None, multiple = False):
|
||||
class VByName(Validator):
|
||||
# Lookup tdb_sql.Thing or tdb_cassandra.Thing objects by fullname.
|
||||
splitter = re.compile('[ ,]+')
|
||||
def __init__(self, param, thing_cls = None, multiple = False,
|
||||
error = errors.NO_THING_ID, backend='sql', **kw):
|
||||
def __init__(self, param, thing_cls=None, multiple=False, limit=None,
|
||||
error=errors.NO_THING_ID, backend='sql', **kw):
|
||||
# Limit param only applies when multiple is True
|
||||
if not multiple and limit is not None:
|
||||
raise TypeError('multiple must be True when limit is set')
|
||||
self.re = fullname_regex(thing_cls)
|
||||
self.multiple = multiple
|
||||
self.limit = limit
|
||||
self._error = error
|
||||
self.backend = backend
|
||||
|
||||
@@ -554,6 +558,8 @@ class VByName(Validator):
|
||||
# tdb_cassandra.Thing objects can't use the regex
|
||||
if items and self.multiple:
|
||||
items = [item for item in self.splitter.split(items)]
|
||||
if self.limit and len(items) > self.limit:
|
||||
return self.set_error(errors.TOO_MANY_THING_IDS)
|
||||
if items:
|
||||
try:
|
||||
return tdb_cassandra.Thing._by_fullname(items, return_dict=False)
|
||||
@@ -563,6 +569,8 @@ class VByName(Validator):
|
||||
if items and self.multiple:
|
||||
items = [item for item in self.splitter.split(items)
|
||||
if item and self.re.match(item)]
|
||||
if self.limit and len(items) > self.limit:
|
||||
return self.set_error(errors.TOO_MANY_THING_IDS)
|
||||
if items and (self.multiple or self.re.match(items)):
|
||||
try:
|
||||
return Thing._by_fullname(items, return_dict=False,
|
||||
|
||||
@@ -724,20 +724,24 @@ def new_message(message, inbox_rels):
|
||||
|
||||
add_message(message)
|
||||
|
||||
def set_unread(message, to, unread):
|
||||
def set_unread(messages, to, unread):
|
||||
# Maintain backwards compatability
|
||||
messages = tup(messages)
|
||||
|
||||
if isinstance(to, Subreddit):
|
||||
for i in ModeratorInbox.set_unread(message, unread):
|
||||
for i in ModeratorInbox.set_unread(messages, unread):
|
||||
kw = dict(insert_items = i) if unread else dict(delete_items = i)
|
||||
add_queries([get_unread_subreddit_messages(i._thing1)], **kw)
|
||||
else:
|
||||
for i in Inbox.set_unread(message, unread, to = to):
|
||||
# All messages should be of the same type
|
||||
for i in Inbox.set_unread(messages, unread, to=to):
|
||||
kw = dict(insert_items = i) if unread else dict(delete_items = i)
|
||||
if isinstance(message, Comment) and not unread:
|
||||
if isinstance(messages[0], Comment) and not unread:
|
||||
add_queries([get_unread_comments(i._thing1)], **kw)
|
||||
add_queries([get_unread_selfreply(i._thing1)], **kw)
|
||||
elif i._name == 'selfreply':
|
||||
add_queries([get_unread_selfreply(i._thing1)], **kw)
|
||||
elif isinstance(message, Comment):
|
||||
elif isinstance(messages[0], Comment):
|
||||
add_queries([get_unread_comments(i._thing1)], **kw)
|
||||
else:
|
||||
add_queries([get_unread_messages(i._thing1)], **kw)
|
||||
|
||||
@@ -1273,15 +1273,19 @@ class Inbox(MultiRelation('inbox',
|
||||
return i
|
||||
|
||||
@classmethod
|
||||
def set_unread(cls, thing, unread, to = None):
|
||||
inbox_rel = cls.rel(Account, thing.__class__)
|
||||
def set_unread(cls, things, unread, to=None):
|
||||
things = tup(things)
|
||||
if len(set(type(x) for x in things)) != 1:
|
||||
raise TypeError('things must only be of a single type')
|
||||
thing_ids = [x._id for x in things]
|
||||
inbox_rel = cls.rel(Account, things[0].__class__)
|
||||
if to:
|
||||
inbox = inbox_rel._query(inbox_rel.c._thing2_id == thing._id,
|
||||
eager_load = True)
|
||||
else:
|
||||
inbox = inbox_rel._query(inbox_rel.c._thing2_id == thing._id,
|
||||
inbox = inbox_rel._query(inbox_rel.c._thing2_id == thing_ids,
|
||||
inbox_rel.c._thing1_id == to._id,
|
||||
eager_load = True)
|
||||
eager_load=True)
|
||||
else:
|
||||
inbox = inbox_rel._query(inbox_rel.c._thing2_id == thing_ids,
|
||||
eager_load=True)
|
||||
res = []
|
||||
for i in inbox:
|
||||
if i:
|
||||
@@ -1320,9 +1324,10 @@ class ModeratorInbox(Relation(Subreddit, Message)):
|
||||
return i
|
||||
|
||||
@classmethod
|
||||
def set_unread(cls, thing, unread):
|
||||
inbox = cls._query(cls.c._thing2_id == thing._id,
|
||||
eager_load = True)
|
||||
def set_unread(cls, things, unread):
|
||||
things = tup(things)
|
||||
thing_ids = [x._id for x in things]
|
||||
inbox = cls._query(cls.c._thing2_id == thing_ids, eager_load=True)
|
||||
res = []
|
||||
for i in inbox:
|
||||
if i:
|
||||
|
||||
Reference in New Issue
Block a user