From 42ed57a24c61adbd783b93fa22c19f4f586e0379 Mon Sep 17 00:00:00 2001 From: bsimpson63 Date: Sun, 21 Oct 2012 11:28:31 -0400 Subject: [PATCH] Delete the jury system. --- r2/r2/config/routing.py | 2 - r2/r2/controllers/api.py | 45 ----- r2/r2/controllers/front.py | 65 +------ r2/r2/lib/db/queries.py | 15 +- r2/r2/lib/pages/things.py | 10 +- r2/r2/lib/strings.py | 2 - r2/r2/lib/utils/__init__.py | 2 +- r2/r2/lib/utils/admin_utils.py | 27 --- r2/r2/lib/utils/trial_utils.py | 237 -------------------------- r2/r2/models/__init__.py | 2 - r2/r2/models/account.py | 6 - r2/r2/models/admintools.py | 8 +- r2/r2/models/builder.py | 1 - r2/r2/models/jury.py | 103 ----------- r2/r2/models/link.py | 17 -- r2/r2/models/subreddit.py | 4 - r2/r2/models/trial.py | 211 ----------------------- r2/r2/public/static/css/reddit.css | 66 +------ r2/r2/public/static/js/reddit.js | 18 -- r2/r2/templates/link.html | 11 +- r2/r2/templates/linkontrial.html | 81 --------- r2/r2/templates/prefoptions.html | 2 +- r2/r2/templates/printablebuttons.html | 23 --- 23 files changed, 14 insertions(+), 944 deletions(-) delete mode 100644 r2/r2/lib/utils/admin_utils.py delete mode 100644 r2/r2/lib/utils/trial_utils.py delete mode 100644 r2/r2/models/jury.py delete mode 100644 r2/r2/models/trial.py delete mode 100644 r2/r2/templates/linkontrial.html diff --git a/r2/r2/config/routing.py b/r2/r2/config/routing.py index 1ad4bf29e..6eab4c2f3 100644 --- a/r2/r2/config/routing.py +++ b/r2/r2/config/routing.py @@ -115,8 +115,6 @@ def make_map(): mc('/prefs/:location', controller='forms', action='prefs', location='options') - mc('/depmod', controller='forms', action='depmod') - mc('/info/0:article/*rest', controller='front', action='oldinfo', dest='comments', type='ancient') mc('/info/:article/:dest/:comment', controller='front', diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 1b09e70d5..2b323585e 100755 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -42,7 +42,6 @@ from r2.lib.pages import (EnemyList, FriendList, ContributorList, ModList, from r2.lib.pages import FlairList, FlairCsv, FlairTemplateEditor, \ FlairSelector from r2.lib.pages import PrefApps -from r2.lib.utils.trial_utils import indict, trial_info from r2.lib.pages.things import wrap_links, default_thing_wrapper from r2.models.last_modified import LastModified @@ -952,15 +951,6 @@ class ApiController(RedditController, OAuth2ResourceController): return c.user.add_enemy(block_acct) - @noresponse(VAdmin(), VModhash(), - thing = VByName('id')) - def POST_indict(self, thing): - '''put something on trial''' - if not thing: - log_text("indict: no thing", level="warning") - - indict(thing) - @require_oauth2_scope("edit") @validatedForm(VUser(), VModhash(), @@ -1157,41 +1147,6 @@ class ApiController(RedditController, OAuth2ResourceController): VRatelimit.ratelimit(rate_user=True, rate_ip = True, prefix = "rate_share_") - @noresponse(VUser(), - VModhash(), - ip = ValidIP(), - dir = VInt('dir', min=-1, max=1), - thing = VByName('id')) - def POST_juryvote(self, dir, thing, ip): - if not thing: - log_text("juryvote: no thing", level="warning") - return - - if not ip: - log_text("juryvote: no ip", level="warning") - return - - if dir is None: - log_text("juryvote: no dir", level="warning") - return - - j = Jury.by_account_and_defendant(c.user, thing) - - if not trial_info([thing]).get(thing._fullname,False): - log_text("juryvote: not on trial", level="warning") - return - - if not j: - log_text("juryvote: not on the jury", level="warning") - return - - log_text("juryvote", - "%s cast a %d juryvote on %s" % (c.user.name, dir, thing._id36), - level="info") - - j._name = str(dir) - j._date = c.start_time - j._commit() @require_oauth2_scope("vote") @noresponse(VUser(), diff --git a/r2/r2/controllers/front.py b/r2/r2/controllers/front.py index 48d2f2d8f..2c6378902 100755 --- a/r2/r2/controllers/front.py +++ b/r2/r2/controllers/front.py @@ -492,9 +492,6 @@ class FrontController(RedditController, OAuth2ResourceController): query = c.site.get_reported() elif location == 'spam': query = c.site.get_spam() - elif location == 'trials': - query = c.site.get_trials() - num = 1000 elif location == 'modqueue': query = c.site.get_modqueue() elif location == 'unmoderated': @@ -518,14 +515,12 @@ class FrontController(RedditController, OAuth2ResourceController): return x.reported > 0 and not x._spam elif location == "spam": return x._spam - elif location == "trials": - return not getattr(x, "verdict", None) elif location == "modqueue": if x.reported > 0 and not x._spam: return True # reported but not banned verdict = getattr(x, "verdict", None) if verdict is None: - return True # anything without a verdict (i.e., trials) + return True # anything without a verdict if x._spam and verdict != 'mod-removed': return True # spam, unless banned by a moderator return False @@ -564,11 +559,8 @@ class FrontController(RedditController, OAuth2ResourceController): else: raise ValueError - if ((level == 'mod' and - location in ('reports', 'spam', 'trials', 'modqueue', 'unmoderated')) - or - (level == 'all' and - location == 'trials')): + if (level == 'mod' and + location in ('reports', 'spam', 'modqueue', 'unmoderated')): pane = self._make_spamlisting(location, num, after, reverse, count) if c.user.pref_private_feeds: extension_handling = "private" @@ -624,7 +616,7 @@ class FrontController(RedditController, OAuth2ResourceController): stylesheet = (c.site.stylesheet_contents_user or c.site.stylesheet_contents) pane = SubredditStylesheetSource(stylesheet_contents=stylesheet) - elif (location in ('reports', 'spam', 'trials', 'modqueue', 'unmoderated') + elif (location in ('reports', 'spam', 'modqueue', 'unmoderated') and is_moderator): c.allow_styles = True pane = self._make_spamlisting(location, num, after, reverse, count) @@ -1134,55 +1126,6 @@ class FormsController(RedditController): return BoringPage(_("reset password"), content=ResetPassword(key=key, done=done)).render() - @validate(VUser()) - def GET_depmod(self): - displayPane = PaneStack() - - active_trials = {} - finished_trials = {} - - juries = Jury.by_account(c.user) - - trials = trial_info([j._thing2 for j in juries]) - - for j in juries: - defendant = j._thing2 - - if trials.get(defendant._fullname, False): - active_trials[defendant._fullname] = j._name - else: - finished_trials[defendant._fullname] = j._name - - if active_trials: - fullnames = sorted(active_trials.keys(), reverse=True) - - def my_wrap(thing): - w = Wrapped(thing) - w.hide_score = True - w.likes = None - w.trial_mode = True - w.render_class = LinkOnTrial - w.juryvote = active_trials[thing._fullname] - return w - - listing = wrap_links(fullnames, wrapper=my_wrap) - displayPane.append(InfoBar(strings.active_trials, - extra_class="mellow")) - displayPane.append(listing) - - if finished_trials: - fullnames = sorted(finished_trials.keys(), reverse=True) - listing = wrap_links(fullnames) - displayPane.append(InfoBar(strings.finished_trials, - extra_class="mellow")) - displayPane.append(listing) - - displayPane.append(InfoBar(strings.more_info_link % - dict(link="/help/deputies"), - extra_class="mellow")) - - return Reddit(content = displayPane).render() - @validate(VUser(), location = nop("location")) def GET_prefs(self, location=''): diff --git a/r2/r2/lib/db/queries.py b/r2/r2/lib/db/queries.py index e2bea5c39..477f73264 100755 --- a/r2/r2/lib/db/queries.py +++ b/r2/r2/lib/db/queries.py @@ -20,7 +20,7 @@ # Inc. All Rights Reserved. ############################################################################### -from r2.models import Account, Link, Comment, Trial, Vote, SaveHide, Report +from r2.models import Account, Link, Comment, Vote, SaveHide, Report from r2.models import Message, Inbox, Subreddit, ModContribSR, ModeratorInbox, MultiReddit from r2.lib.db.thing import Thing, Merge from r2.lib.db.operators import asc, desc, timeago @@ -459,19 +459,6 @@ class QueryishList(list): else: raise StopIteration -def get_trials_links(sr): - l = Trial.defendants_by_sr(sr) - s = QueryishList(l) - s._sort = [db_sort('new')] - return s - -def get_trials(sr): - if isinstance(sr, (ModContribSR, MultiReddit)): - srs = Subreddit._byID(sr.sr_ids, return_dict=False) - return get_trials_links(srs) - else: - return get_trials_links(sr) - @merged_cached_query def get_modqueue(sr): q = [] diff --git a/r2/r2/lib/pages/things.py b/r2/r2/lib/pages/things.py index 4dd908504..25d947875 100644 --- a/r2/r2/lib/pages/things.py +++ b/r2/r2/lib/pages/things.py @@ -35,10 +35,9 @@ class PrintableButtons(Styled): def __init__(self, style, thing, show_delete = False, show_report = True, show_distinguish = False, show_marknsfw = False, - show_unmarknsfw = False, show_indict = False, is_link=False, + show_unmarknsfw = False, is_link=False, show_flair = False, **kw): - show_ignore = (thing.show_reports or - (thing.reveal_trial_info and not thing.show_spam)) + show_ignore = thing.show_reports approval_checkmark = getattr(thing, "approval_checkmark", None) show_approve = (thing.show_spam or show_ignore or (is_link and approval_checkmark is None)) and not thing._deleted @@ -54,7 +53,6 @@ class PrintableButtons(Styled): show_delete = show_delete, show_approve = show_approve, show_report = show_report, - show_indict = show_indict, show_distinguish = show_distinguish, show_marknsfw = show_marknsfw, show_unmarknsfw = show_unmarknsfw, @@ -78,9 +76,6 @@ class LinkButtons(PrintableButtons): if c.user_is_admin and thing.promoted is None: show_report = False - show_indict = True - else: - show_indict = False if (thing.can_ban or is_author) and not thing.nsfw: show_marknsfw = True @@ -129,7 +124,6 @@ class LinkButtons(PrintableButtons): hidden = thing.hidden, show_delete = show_delete, show_report = show_report and c.user_is_loggedin, - show_indict = show_indict, show_distinguish = show_distinguish, show_marknsfw = show_marknsfw, show_unmarknsfw = show_unmarknsfw, diff --git a/r2/r2/lib/strings.py b/r2/r2/lib/strings.py index d341f2e27..58fede416 100644 --- a/r2/r2/lib/strings.py +++ b/r2/r2/lib/strings.py @@ -87,8 +87,6 @@ string_dict = dict( sr_created = _('your reddit has been created'), - active_trials = _("we haven't yet decided whether these things are spam, so you have a chance to change your vote:"), - finished_trials = _("it's too late to change your vote on these things (the verdict has been issued):"), more_info_link = _("visit [%(link)s](%(link)s) for more information"), sr_messages = dict( diff --git a/r2/r2/lib/utils/__init__.py b/r2/r2/lib/utils/__init__.py index dd4f7b51f..b9bfaa390 100644 --- a/r2/r2/lib/utils/__init__.py +++ b/r2/r2/lib/utils/__init__.py @@ -28,4 +28,4 @@ from cmd_utils import * try: from r2admin.lib.admin_utils import * except ImportError: - from admin_utils import * + pass diff --git a/r2/r2/lib/utils/admin_utils.py b/r2/r2/lib/utils/admin_utils.py deleted file mode 100644 index 168fd9cb3..000000000 --- a/r2/r2/lib/utils/admin_utils.py +++ /dev/null @@ -1,27 +0,0 @@ -# The contents of this file are subject to the Common Public Attribution -# License Version 1.0. (the "License"); you may not use this file except in -# compliance with the License. You may obtain a copy of the License at -# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public -# License Version 1.1, but Sections 14 and 15 have been added to cover use of -# software over a computer network and provide for limited attribution for the -# Original Developer. In addition, Exhibit A has been modified to be consistent -# with Exhibit B. -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for -# the specific language governing rights and limitations under the License. -# -# The Original Code is reddit. -# -# The Original Developer is the Initial Developer. The Initial Developer of -# the Original Code is reddit Inc. -# -# All portions of the code written by reddit are Copyright (c) 2006-2012 reddit -# Inc. All Rights Reserved. -############################################################################### - -def jury_cache_dict(account, ip, slash16): - return {"recent-juror-key": 1} - -def voir_dire_priv (account, ip, slash16, defendant, sr): - return True diff --git a/r2/r2/lib/utils/trial_utils.py b/r2/r2/lib/utils/trial_utils.py deleted file mode 100644 index 650d79658..000000000 --- a/r2/r2/lib/utils/trial_utils.py +++ /dev/null @@ -1,237 +0,0 @@ -# The contents of this file are subject to the Common Public Attribution -# License Version 1.0. (the "License"); you may not use this file except in -# compliance with the License. You may obtain a copy of the License at -# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public -# License Version 1.1, but Sections 14 and 15 have been added to cover use of -# software over a computer network and provide for limited attribution for the -# Original Developer. In addition, Exhibit A has been modified to be consistent -# with Exhibit B. -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for -# the specific language governing rights and limitations under the License. -# -# The Original Code is reddit. -# -# The Original Developer is the Initial Developer. The Initial Developer of -# the Original Code is reddit Inc. -# -# All portions of the code written by reddit are Copyright (c) 2006-2012 reddit -# Inc. All Rights Reserved. -############################################################################### - -from pylons import c, g, request -from r2.lib.utils import jury_cache_dict, voir_dire_priv, tup -from r2.lib.memoize import memoize -from r2.lib.log import log_text -import random as rand - -# Hardcache lifetime for a trial. -# The regular hardcache reaper should never run on one of these, -# since a mistrial should be declared if the trial is still open -# after 24 hours. So the "3 days" expiration isn't really real. -TRIAL_TIME = 3 * 86400 - -def trial_key(thing): - return "trial-" + thing._fullname - -def trial_info(things): - things = tup(things) - keys = dict((trial_key(thing), thing._fullname) - for thing in things) -# TODO: disabling trial lookup for now, since there aren't any -# vals = g.hardcache.get_multi(keys) - vals = {} - return dict((keys[key], val) - for (key, val) - in vals.iteritems()) - -def end_trial(thing, verdict=None): - from r2.models import Trial - if trial_info(thing): - g.hardcache.delete(trial_key(thing)) - Trial.all_defendants(_update=True) - - if verdict is not None: - thing.verdict = verdict - thing._commit() - -def indict(defendant): - from r2.models import Trial - tk = trial_key(defendant) - - rv = False - if defendant._deleted: - result = "already deleted" - elif getattr(defendant, "promoted", None) is not None: - result = "it's promoted" - elif hasattr(defendant, "verdict") and defendant.verdict is not None: - result = "it already has a verdict" - elif g.hardcache.get(tk): - result = "it's already on trial" - else: - # The spams/koshers dict is just a infrequently-updated cache; the - # official source of the data is the Jury relation. - g.hardcache.set(tk, dict(spams=0, koshers=0), TRIAL_TIME) - Trial.all_defendants(_update=True) - result = "it's now indicted: %s" % tk - rv = True - - log_text("indict_result", "%s: %s" % (defendant._id36, result), level="info") - - return rv - -# These are spam/kosher votes, not up/down votes -def update_voting(defendant, koshers, spams): - tk = trial_key(defendant) - d = g.hardcache.get(tk) - if d is None: - log_text("update_voting() fail", - "%s not on trial" % defendant._id36, - level="error") - else: - d["koshers"] = koshers - d["spams"] = spams - g.hardcache.set(tk, d, TRIAL_TIME) - -# Check to see if a juror is eligible to serve on a jury for a given link. -def voir_dire(account, ip, slash16, defendants_assigned_to, defendant, sr): - from r2.models import Link - - if defendant._deleted: - g.log.debug("%s is deleted" % defendant) - return False - - if defendant._id in defendants_assigned_to: - g.log.debug("%s is already assigned to %s" % (account.name, defendant)) - return False - - if not isinstance(defendant, Link): - g.log.debug("%s can't serve on a jury for %s: it's not a link" % - account.name, defendant) - return False - - if g.debug: - return True - - if not voir_dire_priv(account, ip, slash16, defendant, sr): - return False - - return True - -def assign_trial(account, juries_already_on, ip, slash16): - from r2.models import Jury, Subreddit, Trial - from r2.lib.db import queries - - defendants_assigned_to = [] - for jury in juries_already_on: - defendants_assigned_to.append(jury._thing2_id) - - subscribed_sr_ids = Subreddit.user_subreddits(account, ids=True, limit=None) - - # Pull defendants, except ones which already have lots of juryvotes - defs = Trial.all_defendants(quench=True) - - # Filter out defendants outside this user's subscribed SRs - defs = filter (lambda d: d.sr_id in subscribed_sr_ids, defs) - - # Dictionary of sr_id => SR for all defendants' SRs - srs = Subreddit._byID(set([ d.sr_id for d in defs ])) - - # Dictionary of sr_id => eligibility bool - submit_srs = {} - for sr_id, sr in srs.iteritems(): - submit_srs[sr_id] = sr.can_submit(account) and not sr._spam - - # Filter out defendants with ineligible SRs - defs = filter (lambda d: submit_srs.get(d.sr_id), defs) - - likes = queries.get_likes(account, defs) - - if not g.debug: - # Filter out things that the user has upvoted or downvoted - defs = filter (lambda d: likes.get((account, d)) is None, defs) - - # Prefer oldest trials - defs.sort(key=lambda x: x._date) - - for defendant in defs: - sr = srs[defendant.sr_id] - - if voir_dire(account, ip, slash16, defendants_assigned_to, defendant, sr): - j = Jury._new(account, defendant) - return defendant - - return None - -def populate_spotlight(): - raise Exception("this function is broken (re: ip_and_slash16) and pending demolition") - - from r2.models import Jury - from r2.lib.db.thing import NotFound - - if not (c.user_is_loggedin and c.user.jury_betatester()): - g.log.debug("not eligible") - return None - - try: - juries_already_on = Jury.by_account(c.user) - except NotFound: - # This can happen if Jury.delete_old() just so happens to be cleaning - # up this user's old Jury rels while they're visiting the front page. - # In this unlucky case, just skip the 20% nagging below. - juries_already_on = [] - - # If they're already on a jury, and haven't yet voted, re-show - # it every five or so times. - if rand.random() < 0.2: - unvoted = filter(lambda j: j._name == '0', juries_already_on) - defs = [u._thing2 for u in unvoted] - active_trials = trial_info(defs) - for d in defs: - if active_trials.get(d._fullname, False): - return d - - if not g.cache.add("global-jury-key", True, 5): - g.log.debug("not yet time to add another juror") - return None - - ip, slash16 = ip_and_slash16(request) - - jcd = jury_cache_dict(c.user, ip, slash16) - - if jcd is None: - g.cache.delete("global-jury-key") - return None - - if g.cache.get_multi(jcd.keys()) and not g.debug: - g.log.debug("recent juror") - g.cache.delete("global-jury-key") - return None - - trial = assign_trial(c.user, juries_already_on, ip, slash16) - - if trial is None: - g.log.debug("nothing available") - g.cache.delete("global-jury-key") - return None - - for k, v in jcd.iteritems(): - g.cache.set(k, True, v) - - log_text("juryassignment", - "%s was just assigned to the jury for %s" % (c.user.name, trial._id36), - level="info") - - return trial - -def look_for_verdicts(): - from r2.models import Trial, Jury - - print "checking all trials for verdicts..." - for defendant in Trial.all_defendants(): - print "Looking at reddit.com/comments/%s/x" % defendant._id36 - v = Trial(defendant).check_verdict() - print "Verdict: %r" % v - - Jury.delete_old(verbose=True, limit=1000) diff --git a/r2/r2/models/__init__.py b/r2/r2/models/__init__.py index 194b9d03d..fad35c50f 100644 --- a/r2/r2/models/__init__.py +++ b/r2/r2/models/__init__.py @@ -29,8 +29,6 @@ from report import * from subreddit import * from flair import * from award import * -from jury import * -from trial import * from ad import * from bidding import * from mail_queue import Email, has_opted_out, opt_count diff --git a/r2/r2/models/account.py b/r2/r2/models/account.py index 6a6496f00..1f4a105ef 100644 --- a/r2/r2/models/account.py +++ b/r2/r2/models/account.py @@ -177,12 +177,6 @@ class Account(Thing): # Legacy, None means user may wiki return True return self.wiki_override - - def jury_betatester(self): - if g.cache.get("jury-killswitch"): - return False - else: - return True def all_karmas(self): """returns a list of tuples in the form (name, hover-text, link_karma, diff --git a/r2/r2/models/admintools.py b/r2/r2/models/admintools.py index a7ba3b65b..20c34ade9 100644 --- a/r2/r2/models/admintools.py +++ b/r2/r2/models/admintools.py @@ -369,10 +369,6 @@ def ip_span(ip): return '' % ip def filter_quotas(unfiltered): - from r2.lib.utils.trial_utils import trial_info - - trials = trial_info(unfiltered) - now = datetime.now(g.tz) baskets = { @@ -408,9 +404,7 @@ def filter_quotas(unfiltered): 'admin-approved', 'mod-approved') # Then, make sure it's worthy of quota-clogging - if trials.get(item._fullname): - pass - elif item._spam: + if item._spam: pass elif item._deleted: pass diff --git a/r2/r2/models/builder.py b/r2/r2/models/builder.py index ea90a3a5f..bfc1ed1ca 100755 --- a/r2/r2/models/builder.py +++ b/r2/r2/models/builder.py @@ -228,7 +228,6 @@ class Builder(object): w.show_reports = False w.show_spam = False w.can_ban = False - w.reveal_trial_info = False w.use_big_modbuttons = False if (c.user_is_admin diff --git a/r2/r2/models/jury.py b/r2/r2/models/jury.py deleted file mode 100644 index 6c788e60c..000000000 --- a/r2/r2/models/jury.py +++ /dev/null @@ -1,103 +0,0 @@ -# The contents of this file are subject to the Common Public Attribution -# License Version 1.0. (the "License"); you may not use this file except in -# compliance with the License. You may obtain a copy of the License at -# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public -# License Version 1.1, but Sections 14 and 15 have been added to cover use of -# software over a computer network and provide for limited attribution for the -# Original Developer. In addition, Exhibit A has been modified to be consistent -# with Exhibit B. -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for -# the specific language governing rights and limitations under the License. -# -# The Original Code is reddit. -# -# The Original Developer is the Initial Developer. The Initial Developer of -# the Original Code is reddit Inc. -# -# All portions of the code written by reddit are Copyright (c) 2006-2012 reddit -# Inc. All Rights Reserved. -############################################################################### - -from r2.lib.db.thing import DataThing, Thing, MultiRelation, Relation -from r2.lib.db.thing import NotFound, load_things -from r2.lib.db.userrel import UserRel -from r2.lib.db.operators import asc, desc, lower -from r2.lib.memoize import memoize -from r2.lib.utils import timeago -from r2.models import Account, Link -from pylons import c, g, request - -class Jury(MultiRelation('jury', - Relation(Account, Link))): - @classmethod - def _new(cls, account, defendant): - j = Jury(account, defendant, "0") - - j._commit() - - Jury.by_account(account, _update=True) - Jury.by_defendant(defendant, _update=True) - - return j - - @classmethod - @memoize('jury.by_account') - def by_account_cache(cls, account_id): - q = cls._query(cls.c._thing1_id == account_id) - q._limit = 100 - return [ j._fullname for j in q ] - - @classmethod - def by_account(cls, account, _update=False): - rel_ids = cls.by_account_cache(account._id, _update=_update) - juries = DataThing._by_fullname(rel_ids, data=True, - return_dict = False) - if juries: - load_things(juries, load_data=True) - return juries - - @classmethod - @memoize('jury.by_defendant') - def by_defendant_cache(cls, defendant_id): - q = cls._query(cls.c._thing2_id == defendant_id) - q._limit = 1000 - return [ j._fullname for j in q ] - - @classmethod - def by_defendant(cls, defendant, _update=False): - rel_ids = cls.by_defendant_cache(defendant._id, _update=_update) - juries = DataThing._by_fullname(rel_ids, data=True, - return_dict = False) - if juries: - load_things(juries, load_data=True) - return juries - - @classmethod - def by_account_and_defendant(cls, account, defendant): - q = cls._fast_query(account, defendant, ("-1", "0", "1")) - v = filter(None, q.values()) - if v: - return v[0] - - @classmethod - def delete_old(cls, age="3 days", limit=500, verbose=False): - cutoff = timeago(age) - q = cls._query(cls.c._date < cutoff) - q._limit = limit - - accounts = set() - defendants = set() - for j in q: - accounts.add(j._thing1) - defendants.add(j._thing2) - j._delete() - - for a in accounts: - Jury.by_account(a, _update=True) - - for d in defendants: - if verbose: - print "Deleting juries for defendant %s" % d._fullname - Jury.by_defendant(d, _update=True) diff --git a/r2/r2/models/link.py b/r2/r2/models/link.py index d97b33bfd..42229d53f 100755 --- a/r2/r2/models/link.py +++ b/r2/r2/models/link.py @@ -24,7 +24,6 @@ from r2.lib.db.thing import Thing, Relation, NotFound, MultiRelation, \ CreationError from r2.lib.db.operators import desc from r2.lib.utils import base_url, tup, domain, title_to_url, UrlParser -from r2.lib.utils.trial_utils import trial_info from account import Account, DeletedUser from subreddit import Subreddit, DomainSR from printable import Printable @@ -351,8 +350,6 @@ class Link(Thing, Printable): else: saved = hidden = clicked = {} - trials = trial_info(wrapped) - for item in wrapped: show_media = False if not hasattr(item, "score_fmt"): @@ -507,8 +504,6 @@ class Link(Thing, Printable): item.author = DeletedUser() item.as_deleted = True - item.trial_info = trials.get(item._fullname, None) - item.approval_checkmark = None item_age = datetime.now(g.tz) - item._date @@ -529,10 +524,6 @@ class Link(Thing, Printable): else: item.approval_checkmark = _("approved by a moderator") - if item.trial_info is not None: - item.reveal_trial_info = True - item.use_big_modbuttons = True - item.expunged = False if item.is_self: item.expunged = Link._should_expunge_selftext(item) @@ -1364,14 +1355,6 @@ class Inbox(MultiRelation('inbox', res.append(i) return res -class LinkOnTrial(Printable): - @classmethod - def add_props(cls, user, wrapped): - Link.add_props(user, wrapped) - for item in wrapped: - item.rowstyle = "link ontrial" - # Run this last - Printable.add_props(user, wrapped) class ModeratorInbox(Relation(Subreddit, Message)): #TODO: shouldn't dupe this diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index bcd6906d2..61e58b495 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -480,10 +480,6 @@ class Subreddit(Thing, Printable): from r2.lib.db import queries return queries.get_reported(self) - def get_trials(self): - from r2.lib.db import queries - return queries.get_trials(self) - def get_modqueue(self): from r2.lib.db import queries return queries.get_modqueue(self) diff --git a/r2/r2/models/trial.py b/r2/r2/models/trial.py deleted file mode 100644 index 1d5ddd5c2..000000000 --- a/r2/r2/models/trial.py +++ /dev/null @@ -1,211 +0,0 @@ -# The contents of this file are subject to the Common Public Attribution -# License Version 1.0. (the "License"); you may not use this file except in -# compliance with the License. You may obtain a copy of the License at -# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public -# License Version 1.1, but Sections 14 and 15 have been added to cover use of -# software over a computer network and provide for limited attribution for the -# Original Developer. In addition, Exhibit A has been modified to be consistent -# with Exhibit B. -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for -# the specific language governing rights and limitations under the License. -# -# The Original Code is reddit. -# -# The Original Developer is the Initial Developer. The Initial Developer of -# the Original Code is reddit Inc. -# -# All portions of the code written by reddit are Copyright (c) 2006-2012 reddit -# Inc. All Rights Reserved. -############################################################################### - -from r2.models import Thing, Link, Subreddit, AllSR, admintools -from r2.lib.utils import Storage, tup -from r2.lib.memoize import memoize -from datetime import datetime -from pylons import g - -class Trial(Storage): - def __init__(self, defendant): - from r2.lib.utils.trial_utils import trial_info - - if not defendant._loaded: - defendant._load() - if not trial_info(defendant): - raise ValueError ("Defendant %s is not on trial" % defendant._id) - self.defendant = defendant - - def convict(self, details = ''): -# if self.defendant._spam: -# TODO: PM submitter, maybe? -# else: -# TODO: PM submitter, maybe? - admintools.spam(self.defendant, auto=False, moderator_banned=True, - banner="deputy moderation" + details) - - def acquit(self, details = ''): - admintools.unspam(self.defendant, unbanner="deputy moderation" + details) - -# if self.defendant._spam: -# TODO: PM submitter -# TODO: reset submission time: -# self.defendant._date = datetime.now(g.tz) - - def mistrial(self): - #TODO: PM mods - if self.defendant._spam: - pass #TODO: PM submitter - - def verdict(self): - from r2.models import Jury - from r2.lib.utils.trial_utils import update_voting - - koshers = 0 - spams = 0 - nones = 0 - - now = datetime.now(g.tz) - defendant_age = now - self.defendant._date - if defendant_age.days > 0: - return ("jury timeout", None, None) - - latest_juryvote = None - for j in Jury.by_defendant(self.defendant): - if j._name == "0": - nones += 1 - continue - - # For non-zero votes, update latest_juryvote - if latest_juryvote is None: - latest_juryvote = j._date - else: - latest_juryvote = max(latest_juryvote, j._date) - - if j._name == "1": - koshers += 1 - elif j._name == "-1": - spams += 1 - else: - raise ValueError("weird jury vote: [%s]" % j._name) - - # The following trace is temporary; it'll be removed once this - # is done via cron job as opposed to manually - print "%d koshers, %d spams, %d haven't voted yet" % (koshers, spams, nones) - - update_voting(self.defendant, koshers, spams) - - total_votes = koshers + spams - - if total_votes < 7: - g.log.debug("not enough votes yet") - return (None, koshers, spams) - - # Stop showing this in the spotlight box once it has 20 votes - if total_votes >= 20: - g.cache.set("quench_jurors-" + self.defendant._fullname, True) - quenching = True - else: - quenching = False - - # If a trial is less than an hour old, and votes are still trickling - # in (i.e., there was one in the past five minutes), we're going to - # require a nearly unanimous opinion to end the trial without - # waiting for more votes. - if defendant_age.seconds < 3600 and (now - latest_juryvote).seconds < 300: - trickling = True - else: - trickling = False - - kosher_pct = float(koshers) / float(total_votes) - - if kosher_pct < 0.13: - return ("guilty", koshers, spams) - elif kosher_pct > 0.86: - return ("innocent", koshers, spams) - elif trickling: - g.log.debug("votes still trickling in") - return (None, koshers, spams) - elif kosher_pct < 0.34: - return ("guilty", koshers, spams) - elif kosher_pct > 0.66: - return ("innocent", koshers, spams) - elif not quenching: - g.log.debug("not yet quenching") - return (None, koshers, spams) - # At this point, we're not showing the link to any new jurors, and - # the existing jurors haven't changed or submitted votes for several - # minutes, so we're not really expecting to get many more votes. - # Thus, lower our standards for consensus. - elif kosher_pct < 0.3999: - return ("guilty", koshers, spams) - elif kosher_pct > 0.6001: - return ("innocent", koshers, spams) - elif total_votes >= 100: - # This should never really happen; quenching should kick in - # after 20 votes, so new jurors won't be assigned to the - # trial. Just in case something goes wrong, close any trials - # with more than 100 votes. - return ("hung jury", koshers, spams) - else: - g.log.debug("hung jury, so far") - return (None, koshers, spams) # no decision yet; wait for more voters - - def check_verdict(self): - from r2.lib.utils.trial_utils import end_trial - - verdict, koshers, spams = self.verdict() - if verdict is None: - return # no verdict yet - - if verdict in ("jury timeout", "hung jury"): - self.mistrial() - else: - details=", %d-%d" % (spams, koshers) - - if verdict == "guilty": - self.convict(details) - elif verdict == "innocent": - self.acquit(details) - else: - raise ValueError("Invalid verdict [%s]" % verdict) - - end_trial(self.defendant, verdict) - - return verdict - - @classmethod - @memoize('trial.all_defendants') - def all_defendants_cache(cls): - fnames = g.hardcache.backend.ids_by_category("trial") - return fnames - - @classmethod - def all_defendants(cls, quench=False, _update=False): - all = cls.all_defendants_cache(_update=_update) - - defs = Thing._by_fullname(all, data=True).values() - - if quench: - # Used for the spotlight, to filter out trials with over 20 votes; - # otherwise, hung juries would hog the spotlight for an hour as - # their vote counts continued to skyrocket - - return filter (lambda d: - not g.cache.get("quench_jurors-" + d._fullname), - defs) - else: - return defs - - # sr can be plural - @classmethod - def defendants_by_sr(cls, sr): - all = cls.all_defendants() - - if isinstance(sr, AllSR): - return all - - sr = tup(sr) - sr_ids = [ s._id for s in sr ] - - return filter (lambda x: x.sr_id in sr_ids, all) diff --git a/r2/r2/public/static/css/reddit.css b/r2/r2/public/static/css/reddit.css index c9e2cb615..d14f07db7 100755 --- a/r2/r2/public/static/css/reddit.css +++ b/r2/r2/public/static/css/reddit.css @@ -3223,20 +3223,12 @@ form input[type=radio] {margin: 2px .5em 0 0; } border-radius: 3px; } -.entry .buttons li.trial-stamp, .entry .buttons li.reported-stamp { +.entry .buttons li.reported-stamp { border: 1px solid black !important; padding: 0 4px; background-color: #f6e69f; } -.entry .buttons li.trial-stamp .spam { - color: #e00; -} - -.entry .buttons li.trial-stamp .kosher { - color: #090; -} - .suspicious { background-color: #f6e69f } .thing.spam { background-color: #FA8072 } @@ -5202,62 +5194,6 @@ a.pretty-button.positive.pressed { background-image: url(../bg-button-positive-pressed.png); /* SPRITE stretch-x */ } - -/* -.jury-box .pretty-button a.pressed { - margin: -1px 4px -1px 1px; - border-width: 2px; - border-color: black; - color: white; -} -*/ -.organic-listing .ontrial, .help-cover.juryduty { - background-color: #ffecf8; -} - -.organic-listing .ontrial a.title { - color: #555; -} - -.organic-listing .ontrial .midcol { - margin-top: 20px; -} - -.we-need-help { - font-size: larger; - font-weight: bold; - line-height: 18px; -} - -.organic-listing .how-to-classify { - font-weight: bold; -} - -.jury-box .arrow-msg { - display: none; - color: red; - margin-top:5px; -} - -.jury-box .thanks-for-voting { - margin-left: 1em; - display: none; - color: red; -} - -.jury-box .thanks-for-voting a { - margin-left: 1em; -} - -.sitetable .linkontrial { -/* border-top: solid 1px #ccc; */ - padding-top: 5px; -} - -.sitetable .we-need-help { - display: none; -} - .oatmeal img { display: block; margin: 5px auto; diff --git a/r2/r2/public/static/js/reddit.js b/r2/r2/public/static/js/reddit.js index e726bb817..bd3c855da 100644 --- a/r2/r2/public/static/js/reddit.js +++ b/r2/r2/public/static/js/reddit.js @@ -1193,24 +1193,6 @@ function big_mod_action(elem, dir) { return false; } -function juryvote(elem, dir) { - var thing_id = elem.thing_id(); - - if (elem.hasClass("pressed")) { - dir = 0; - } - - elem.toggleClass("pressed"); - elem.siblings(".pretty-button").removeClass("pressed"); - - d = { - id: thing_id, - dir: dir - }; - $.request("juryvote", d, null, true); - elem.siblings(".thanks-for-voting").show(); - return false; -} /* The ready method */ $(function() { diff --git a/r2/r2/templates/link.html b/r2/r2/templates/link.html index e63fc0484..1c43520a1 100755 --- a/r2/r2/templates/link.html +++ b/r2/r2/templates/link.html @@ -42,9 +42,7 @@ <%def name="make_link(name, css_class)"> ## if we're not on a permalink page we'll render the buttons on top - ## (unless it's also a jury duty listing) - %if not (expand or getattr(thing, "trial_mode", None)): + %if not expand: ${bottom_buttons()} %endif @@ -195,8 +192,6 @@ ${parent.thing_data_attributes(what)} data-ups="${what.upvotes}" data-downs="${w ${self.arrow(thing, 1, thing.likes)} %if thing.pref_compress:
- %elif getattr(thing, "trial_mode", None): -
%elif thing.hide_score:
@@ -242,7 +237,7 @@ ${parent.thing_data_attributes(what)} data-ups="${what.upvotes}" data-downs="${w <%def name="thumbnail()"> - %if thing.thumbnail and not getattr(thing, "trial_mode", None): + %if thing.thumbnail: <%call expr="make_link('thumbnail', 'thumbnail ' + (thing.thumbnail if thing.thumbnail_sprited else ''))"> % if not thing.thumbnail_sprited: <% diff --git a/r2/r2/templates/linkontrial.html b/r2/r2/templates/linkontrial.html deleted file mode 100644 index 05c22f8d7..000000000 --- a/r2/r2/templates/linkontrial.html +++ /dev/null @@ -1,81 +0,0 @@ -## The contents of this file are subject to the Common Public Attribution -## License Version 1.0. (the "License"); you may not use this file except in -## compliance with the License. You may obtain a copy of the License at -## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public -## License Version 1.1, but Sections 14 and 15 have been added to cover use of -## software over a computer network and provide for limited attribution for the -## Original Developer. In addition, Exhibit A has been modified to be -## consistent with Exhibit B. -## -## Software distributed under the License is distributed on an "AS IS" basis, -## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for -## the specific language governing rights and limitations under the License. -## -## The Original Code is reddit. -## -## The Original Developer is the Initial Developer. The Initial Developer of -## the Original Code is reddit Inc. -## -## All portions of the code written by reddit are Copyright (c) 2006-2012 -## reddit Inc. All Rights Reserved. -############################################################################### - -<%! - from r2.lib.pages.things import LinkButtons - from r2.lib.pages import WrappedUser -%> - -<%inherit file="link.html"/> -<%namespace file="printablebuttons.html" import="ynbutton" /> -<%namespace file="utils.html" import="plain_link" /> -<%namespace file="utils.html" import="pretty_button" /> - -<%def name="buttons(comments=True, delete=True, report=True, additional='')"> - - -<%def name="arrow(this, dir, mod)"> -
-
- - -<%def name="entry()"> - - ${_("reddit's spam filter needs your help!")} - - - ${parent.entry()} - -
- - ${_("how would you classify this link?")} - - - <% - pos_class = "positive" - neg_class = "negative" - - if not hasattr(thing, "juryvote"): - pass - elif int(thing.juryvote) == 1: - pos_class += " pressed" - elif int(thing.juryvote) == -1: - neg_class += " pressed" - %> - - ${pretty_button(_("off-topic / spam"), "juryvote", -1, neg_class)} - ${pretty_button(_("kosher"), "juryvote", 1, pos_class)} - - - ${_("thanks for voting!")} - - - ${_("Click here for more info.").lower()} - - -
- ${_("those arrows are only for show; they don't actually do anything.")} -
-
- - diff --git a/r2/r2/templates/prefoptions.html b/r2/r2/templates/prefoptions.html index 6043fd7c9..40d0d5524 100644 --- a/r2/r2/templates/prefoptions.html +++ b/r2/r2/templates/prefoptions.html @@ -132,7 +132,7 @@ ${_("link options")} -%if c.user_is_loggedin and c.user.jury_betatester(): +%if c.user_is_loggedin:

${checkbox(_("show the spotlight box on the front page"), "organic")} diff --git a/r2/r2/templates/printablebuttons.html b/r2/r2/templates/printablebuttons.html index 3bd0c5de5..26c7b7dcc 100644 --- a/r2/r2/templates/printablebuttons.html +++ b/r2/r2/templates/printablebuttons.html @@ -33,11 +33,6 @@ ${ynbutton(_("delete"), _("deleted"), "del", "hide_thing")} %endif - %if thing.show_indict: -

  • - ${ynbutton(_("indict"), _("indicted"), "indict")} -
  • - %endif %if thing.can_ban: %if not getattr(thing.thing, "use_big_modbuttons", False): %if not thing.show_spam: @@ -240,24 +235,6 @@ %endif %endif - %if getattr(thing.thing, "reveal_trial_info", False): -
  • - ${_("deputy opinion:")} - - - ${_("%d spam") % thing.thing.trial_info.get("spams", "?")} - - - / - - - ${_("%d kosher") % thing.thing.trial_info.get("koshers", "?")} - -
  • - %endif - %if thing.show_reports and not thing.show_spam:
  • ${strings.reports % thing.thing.reported}