def spam(self, things, auto=True, moderator_banned=False, banner=None, date = None, **kw): from r2.lib.db import queries all_things = tup(things) new_things = [x for x in all_things if not x._spam] # No need to accept reports on things with _spam=True, # since nobody can report them in the first place. Report.accept(new_things, True) for t in all_things: if getattr(t, "promoted", None) is not None: g.log.debug("Refusing to mark promotion %r as spam" % t) continue t._spam = True ban_info = copy(getattr(t, 'ban_info', {})) ban_info.update(auto = auto, moderator_banned = moderator_banned, banned_at = date or datetime.now(g.tz), **kw) if isinstance(banner, dict): ban_info['banner'] = banner[t._fullname] else: ban_info['banner'] = banner t.ban_info = ban_info t._commit() if not auto: self.author_spammer(new_things, True) self.set_last_sr_ban(new_things) queries.ban(new_things)
def spam(self, things, auto, moderator_banned, banner, date = None, **kw): from r2.lib.db import queries things = [x for x in tup(things) if not x._spam] Report.accept(things, True) for t in things: t._spam = True ban_info = copy(getattr(t, 'ban_info', {})) ban_info.update(auto = auto, moderator_banned = moderator_banned, banned_at = date or datetime.now(g.tz), **kw) if isinstance(banner, dict): ban_info['banner'] = banner[t._fullname] else: ban_info['banner'] = banner t.ban_info = ban_info t._commit() changed(t) if not auto: self.author_spammer(things, True) self.set_last_sr_ban(things) queries.ban(things)
def unspam(self, things, unbanner=None, train_spam=True, insert=True): from r2.lib.db import queries things = tup(things) # We want to make unban-all moderately efficient, so when # mass-unbanning, we're going to skip the code below on links that # are already not banned. However, when someone manually clicks # "approve" on an unbanned link, and there's just one, we want do # want to run the code below. That way, the little green checkmark # will have the right mouseover details, the reports will be # cleared, etc. if len(things) > 1: things = [x for x in things if x._spam] Report.accept(things, False) for t in things: ban_info = copy(getattr(t, 'ban_info', {})) ban_info['unbanned_at'] = datetime.now(g.tz) if unbanner: ban_info['unbanner'] = unbanner if ban_info.get('reset_used', None) == None: ban_info['reset_used'] = False else: ban_info['reset_used'] = True t.ban_info = ban_info t._spam = False t._commit() self.author_spammer(things, False) self.set_last_sr_ban(things) queries.unban(things, insert)
def spam(self, things, auto=True, moderator_banned=False, banner=None, date=None, train_spam=True, **kw): from r2.lib.db import queries all_things = tup(things) new_things = [x for x in all_things if not x._spam] Report.accept(all_things, True) for t in all_things: if getattr(t, "promoted", None) is not None: g.log.debug("Refusing to mark promotion %r as spam" % t) continue if not t._spam and train_spam: note = 'spam' elif not t._spam and not train_spam: note = 'remove not spam' elif t._spam and not train_spam: note = 'confirm spam' elif t._spam and train_spam: note = 'reinforce spam' t._spam = True if moderator_banned: t.verdict = 'mod-removed' elif not auto: t.verdict = 'admin-removed' ban_info = copy(getattr(t, 'ban_info', {})) if isinstance(banner, dict): ban_info['banner'] = banner[t._fullname] else: ban_info['banner'] = banner ban_info.update(auto=auto, moderator_banned=moderator_banned, banned_at=date or datetime.now(g.tz), **kw) ban_info['note'] = note t.ban_info = ban_info t._commit() if auto: amqp.add_item("auto_removed", t._fullname) if not auto: self.author_spammer(new_things, True) self.set_last_sr_ban(new_things) queries.ban(all_things, filtered=auto)
def unspam(self, things, moderator_unbanned=True, unbanner=None, train_spam=True, insert=True): from r2.lib.db import queries things = tup(things) # We want to make unban-all moderately efficient, so when # mass-unbanning, we're going to skip the code below on links that # are already not banned. However, when someone manually clicks # "approve" on an unbanned link, and there's just one, we want do # want to run the code below. That way, the little green checkmark # will have the right mouseover details, the reports will be # cleared, etc. if len(things) > 1: things = [x for x in things if x._spam] Report.accept(things, False) inbox_adjustment_counter = Counter() for t in things: ban_info = copy(getattr(t, 'ban_info', {})) ban_info['unbanned_at'] = datetime.now(g.tz) if unbanner: ban_info['unbanner'] = unbanner if ban_info.get('reset_used', None) == None: ban_info['reset_used'] = False else: ban_info['reset_used'] = True t.ban_info = ban_info if isinstance(t, Message) and t._spam and t.to_id: inbox_adjustment_counter[t.to_id] += 1 t._spam = False if moderator_unbanned: t.verdict = 'mod-approved' else: t.verdict = 'admin-approved' t._commit() if isinstance(t, Comment): amqp.add_item("approved_comment", t._fullname) elif isinstance(t, Link): amqp.add_item("approved_link", t._fullname) self.author_spammer(things, False) self.set_last_sr_ban(things) queries.unban(things, insert) self.adjust_inbox_counts(inbox_adjustment_counter)
def unspam(self, things, unbanner = None): Report.accept(things, False) things = [ x for x in tup(things) if x._spam ] for t in things: ban_info = copy(getattr(t, 'ban_info', {})) ban_info['unbanned_at'] = datetime.now(g.tz) if unbanner: ban_info['unbanner'] = unbanner t.ban_info = ban_info t._spam = False t._commit() changed(t) self.author_spammer(things, False) queries.unban(things)
def spam(self, things, auto, moderator_banned, banner, date = None, **kw): Report.accept(things, True) things = [ x for x in tup(things) if not x._spam ] for t in things: t._spam = True ban_info = copy(getattr(t, 'ban_info', {})) ban_info.update(auto = auto, moderator_banned = moderator_banned, banner = banner, banned_at = date or datetime.now(g.tz), **kw) t.ban_info = ban_info t._commit() changed(t) self.author_spammer(things, True) queries.ban(things)
def __init__(self, thing, delete = True, report = True): # is the current user the author? is_author = thing.is_author # do we show the report button? show_report = not is_author and report and thing.can_reply # do we show the delete button? show_delete = is_author and delete and not thing._deleted show_distinguish = (is_author and (thing.can_ban or # Moderator distinguish c.user.employee or # Admin distinguish c.user_special_distinguish)) show_givegold = thing.can_gild PrintableButtons.__init__(self, "commentbuttons", thing, can_save=thing.can_save, is_author = is_author, profilepage = c.profilepage, permalink = thing.permalink, saved = thing.saved, ignore_reports = thing.ignore_reports, full_comment_path = thing.full_comment_path, full_comment_count = thing.full_comment_count, deleted = thing.deleted, parent_permalink = thing.parent_permalink, can_reply = thing.can_reply, show_report = show_report, report_reasons = Report.get_reasons(thing), show_distinguish = show_distinguish, show_delete = show_delete, show_givegold=show_givegold, )
def thing_attr(self, thing, attr): """ For the benefit of subclasses, to lookup attributes which may require more work than a simple getattr (for example, 'author' which has to be gotten from the author_id attribute on most things). """ if attr == "author": if thing.author._deleted: return "[deleted]" return thing.author.name if attr == "author_flair_text": if thing.author._deleted: return None if thing.author.flair_enabled_in_sr(thing.subreddit._id): return getattr(thing.author, "flair_%s_text" % (thing.subreddit._id), None) else: return None if attr == "author_flair_css_class": if thing.author._deleted: return None if thing.author.flair_enabled_in_sr(thing.subreddit._id): return getattr(thing.author, "flair_%s_css_class" % (thing.subreddit._id), None) else: return None elif attr == "created": return time.mktime(thing._date.timetuple()) elif attr == "created_utc": return time.mktime(thing._date.astimezone(pytz.UTC).timetuple()) - time.timezone elif attr == "child": return CachedVariable("childlisting") elif attr == "upvotes": return thing.score elif attr == "downvotes": return 0 if attr == "distinguished": distinguished = getattr(thing, attr, "no") if distinguished == "no": return None return distinguished if attr in ["num_reports", "report_reasons", "banned_by", "approved_by"]: if c.user_is_loggedin and thing.subreddit.is_moderator(c.user): if attr == "num_reports": return thing.reported elif attr == "report_reasons": return Report.get_reasons(thing) ban_info = getattr(thing, "ban_info", {}) if attr == "banned_by": banner = ban_info.get("banner") if ban_info.get("moderator_banned") else True return banner if thing._spam else None elif attr == "approved_by": return ban_info.get("unbanner") if not thing._spam else None return getattr(thing, attr, None)
def unspam(self, things, unbanner = None): from r2.lib.db import queries things = [x for x in tup(things) if x._spam] Report.accept(things, False) for t in things: ban_info = copy(getattr(t, 'ban_info', {})) ban_info['unbanned_at'] = datetime.now(g.tz) if unbanner: ban_info['unbanner'] = unbanner t.ban_info = ban_info t._spam = False t._commit() changed(t) # auto is always False for unbans self.author_spammer(things, False) self.set_last_sr_ban(things) queries.unban(things)
def __init__(self, thing, delete=True, report=True): # is the current user the author? is_author = thing.is_author # do we show the report button? show_report = not is_author and report and thing.can_reply # do we show the delete button? show_delete = is_author and delete and not thing._deleted show_distinguish = ( is_author and (thing.can_ban or # Moderator distinguish c.user.employee or # Admin distinguish c.user_special_distinguish)) show_givegold = thing.can_gild PrintableButtons.__init__( self, "commentbuttons", thing, can_save=thing.can_save, is_author=is_author, profilepage=c.profilepage, permalink=thing.permalink, saved=thing.saved, ignore_reports=thing.ignore_reports, full_comment_path=thing.full_comment_path, full_comment_count=thing.full_comment_count, deleted=thing.deleted, parent_permalink=thing.parent_permalink, can_reply=thing.can_reply, show_report=show_report, report_reasons=Report.get_reasons(thing), show_distinguish=show_distinguish, show_delete=show_delete, show_givegold=show_givegold, )
def perform_actions(self, item, data): """Execute the defined actions on the item.""" # only approve if it's currently removed or reported should_approve = item._spam or (self.reports and item.reported) if self.action == "approve" and should_approve: approvable_author = not data["author"]._spam or self.approve_banned if approvable_author: # TODO: shouldn't need to set train_spam/insert values admintools.unspam( item, moderator_unbanned=True, unbanner=ACCOUNT.name, train_spam=True, insert=item._spam ) log_action = None if isinstance(item, Link): log_action = "approvelink" elif isinstance(item, Comment): log_action = "approvecomment" if log_action: ModAction.create(data["subreddit"], ACCOUNT, log_action, target=item, details="unspam") g.stats.simple_event("automoderator.approve") if self.action in {"remove", "spam"}: spam = self.action == "spam" admintools.spam(item, auto=False, moderator_banned=True, banner=ACCOUNT.name, train_spam=spam) # TODO: shouldn't need to do all of this here modified_thing = None log_action = None if isinstance(item, Link): modified_thing = item log_action = "removelink" elif isinstance(item, Comment): modified_thing = data["link"] log_action = "removecomment" queries.unnotify(item) if modified_thing: set_last_modified(modified_thing, "comments") LastModified.touch(modified_thing._fullname, "Comments") if log_action: log_details = "spam" if spam else "remove" ModAction.create(data["subreddit"], ACCOUNT, log_action, target=item, details=log_details) g.stats.simple_event("automoderator.%s" % self.action) if self.action == "report": if self.report_reason: reason = replace_placeholders(self.report_reason, data, self.parent.matches) else: reason = None Report.new(ACCOUNT, item, reason) admintools.report(item) g.stats.simple_event("automoderator.report") if self.set_nsfw is not None: if item.over_18 != self.set_nsfw: item.over_18 = self.set_nsfw item._commit() # TODO: shouldn't need to do this here log_details = None if not self.set_nsfw: log_details = "remove" ModAction.create(data["subreddit"], ACCOUNT, "marknsfw", target=item, details=log_details) item.update_search_index() if self.set_contest_mode is not None: if item.contest_mode != self.set_contest_mode: item.contest_mode = self.set_contest_mode item._commit() if self.set_sticky is not None: already_stickied = data["subreddit"].sticky_fullname == item._fullname if already_stickied != self.set_sticky: if not self.set_sticky: data["subreddit"].sticky_fullname = None else: data["subreddit"].sticky_fullname = item._fullname data["subreddit"]._commit() # TODO: shouldn't need to do this here if self.set_sticky: log_action = "sticky" else: log_action = "unsticky" ModAction.create(data["subreddit"], ACCOUNT, log_action, target=item) if self.set_flair: # don't overwrite existing flair unless that was specified can_update_flair = False if isinstance(item, Link): if item.flair_text or item.flair_css_class: can_update_flair = self.overwrite_flair else: can_update_flair = True elif isinstance(item, Account): if data["subreddit"].is_flair(item): can_update_flair = self.overwrite_flair else: can_update_flair = True if can_update_flair: text = replace_placeholders(self.set_flair["text"], data, self.parent.matches) cls = replace_placeholders(self.set_flair["class"], data, self.parent.matches) # apply same limits as API to text and class text = text[:64] cls = re.sub(r"[^\w -]", "", cls) classes = cls.split()[:10] classes = [cls[:100] for cls in classes] cls = " ".join(classes) if isinstance(item, Link): item.set_flair(text, cls) elif isinstance(item, Account): item.set_flair(data["subreddit"], text, cls) g.stats.simple_event("automoderator.set_flair")
def __init__(self, thing, comments = True, delete = True, report = True): # is the current user the author? is_author = (c.user_is_loggedin and thing.author and c.user.name == thing.author.name) # do we show the report button? show_report = not is_author and report if c.user_is_admin and thing.promoted is None: show_report = False show_marknsfw = show_unmarknsfw = False show_rescrape = False if thing.can_ban or is_author or (thing.promoted and c.user_is_sponsor): if not thing.nsfw: show_marknsfw = True elif thing.nsfw and not thing.nsfw_str: show_unmarknsfw = True if (not thing.is_self and not (thing.has_thumbnail or thing.media_object)): show_rescrape = True show_givegold = thing.can_gild and (c.permalink_page or c.profilepage) # do we show the delete button? show_delete = is_author and delete and not thing._deleted # disable the delete button for live sponsored links if (is_promoted(thing) and not c.user_is_sponsor): show_delete = False # do we show the distinguish button? among other things, # we never want it to appear on link listings -- only # comments pages show_distinguish = (is_author and (thing.can_ban or # Moderator distinguish c.user.employee or # Admin distinguish c.user_special_distinguish) and getattr(thing, "expand_children", False)) kw = {} if thing.promoted is not None: now = datetime.now(g.tz) kw = dict(promo_url = promo_edit_url(thing), promote_status = getattr(thing, "promote_status", 0), user_is_sponsor = c.user_is_sponsor, traffic_url = promo_traffic_url(thing), is_author = thing.is_author) PrintableButtons.__init__(self, 'linkbuttons', thing, # user existence and preferences is_loggedin = c.user_is_loggedin, # comment link params comment_label = thing.comment_label, commentcls = thing.commentcls, permalink = thing.permalink, # button visibility saved = thing.saved, editable = thing.editable, hidden = thing.hidden, ignore_reports = thing.ignore_reports, show_delete = show_delete, show_report = show_report and c.user_is_loggedin, report_reasons = Report.get_reasons(thing), show_distinguish = show_distinguish, show_marknsfw = show_marknsfw, show_unmarknsfw = show_unmarknsfw, show_flair = thing.can_flair, show_rescrape=show_rescrape, show_givegold=show_givegold, show_comments = comments, # promotion promoted = thing.promoted, is_link = True, **kw)
def _user_reported_query(user_id, thing_cls): rel_cls = Report.rel(Account, thing_cls) return rel_query(rel_cls, user_id, ('-1', '0', '1'))
def __init__(self, thing, comments=True, delete=True, report=True): # is the current user the author? is_author = (c.user_is_loggedin and thing.author and c.user.name == thing.author.name) # do we show the report button? show_report = not is_author and report if c.user_is_admin and thing.promoted is None: show_report = False show_marknsfw = show_unmarknsfw = False show_rescrape = False if thing.can_ban or is_author or (thing.promoted and c.user_is_sponsor): if not thing.nsfw: show_marknsfw = True elif thing.nsfw and not thing.nsfw_str: show_unmarknsfw = True if (not thing.is_self and not (thing.has_thumbnail or thing.media_object)): show_rescrape = True show_givegold = thing.can_gild and (c.permalink_page or c.profilepage) # do we show the delete button? show_delete = is_author and delete and not thing._deleted # disable the delete button for live sponsored links if (is_promoted(thing) and not c.user_is_sponsor): show_delete = False # do we show the distinguish button? among other things, # we never want it to appear on link listings -- only # comments pages show_distinguish = ( is_author and (thing.can_ban or # Moderator distinguish c.user.employee or # Admin distinguish c.user_special_distinguish) and getattr(thing, "expand_children", False)) kw = {} if thing.promoted is not None: now = datetime.now(g.tz) kw = dict(promo_url=promo_edit_url(thing), promote_status=getattr(thing, "promote_status", 0), user_is_sponsor=c.user_is_sponsor, traffic_url=promo_traffic_url(thing), is_author=thing.is_author) PrintableButtons.__init__( self, 'linkbuttons', thing, # user existence and preferences is_loggedin=c.user_is_loggedin, # comment link params comment_label=thing.comment_label, commentcls=thing.commentcls, permalink=thing.permalink, # button visibility saved=thing.saved, editable=thing.editable, hidden=thing.hidden, ignore_reports=thing.ignore_reports, show_delete=show_delete, show_report=show_report and c.user_is_loggedin, report_reasons=Report.get_reasons(thing), show_distinguish=show_distinguish, show_marknsfw=show_marknsfw, show_unmarknsfw=show_unmarknsfw, show_flair=thing.can_flair, show_rescrape=show_rescrape, show_givegold=show_givegold, show_comments=comments, # promotion promoted=thing.promoted, is_link=True, **kw)
def thing_attr(self, thing, attr): """ For the benefit of subclasses, to lookup attributes which may require more work than a simple getattr (for example, 'author' which has to be gotten from the author_id attribute on most things). """ if attr == "author": if thing.author._deleted: return "[deleted]" return thing.author.name if attr == "author_flair_text": if thing.author._deleted: return None if thing.author.flair_enabled_in_sr(thing.subreddit._id): return getattr(thing.author, 'flair_%s_text' % (thing.subreddit._id), None) else: return None if attr == "author_flair_css_class": if thing.author._deleted: return None if thing.author.flair_enabled_in_sr(thing.subreddit._id): return getattr(thing.author, 'flair_%s_css_class' % (thing.subreddit._id), None) else: return None elif attr == "created": return time.mktime(thing._date.timetuple()) elif attr == "created_utc": return (time.mktime(thing._date.astimezone(pytz.UTC).timetuple()) - time.timezone) elif attr == "child": return CachedVariable("childlisting") elif attr == "upvotes": return thing.score elif attr == "downvotes": return 0 if attr == 'distinguished': distinguished = getattr(thing, attr, 'no') if distinguished == 'no': return None return distinguished if attr in [ "num_reports", "report_reasons", "banned_by", "approved_by" ]: if c.user_is_loggedin and thing.subreddit.is_moderator(c.user): if attr == "num_reports": return thing.reported elif attr == "report_reasons": return Report.get_reasons(thing) ban_info = getattr(thing, "ban_info", {}) if attr == "banned_by": banner = (ban_info.get("banner") if ban_info.get('moderator_banned') else True) return banner if thing._spam else None elif attr == "approved_by": return ban_info.get( "unbanner") if not thing._spam else None return getattr(thing, attr, None)
def _user_reported_query(user_id, thing_cls): rel_cls = Report.rel(Account, thing_cls) return rel_query(rel_cls, user_id, ("-1", "0", "1"))