From 5202a824c6509309bd415f13f8ee3297f62de281 Mon Sep 17 00:00:00 2001 From: Brian Simpson Date: Fri, 27 Sep 2013 01:53:48 -0400 Subject: [PATCH] Show how many server seconds the user has paid for. --- r2/example.ini | 2 + r2/r2/lib/app_globals.py | 3 ++ r2/r2/lib/pages/pages.py | 71 +++++++++++++++++++++++++-- r2/r2/public/static/css/reddit.less | 7 +++ r2/r2/templates/serversecondsbar.html | 28 +++++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 r2/r2/templates/serversecondsbar.html diff --git a/r2/example.ini b/r2/example.ini index 45683038f..f9712d34e 100644 --- a/r2/example.ini +++ b/r2/example.ini @@ -611,3 +611,5 @@ listing_chooser_sample_multis = /user/reddit/m/hello, /user/reddit/m/world listing_chooser_gold_multi = /user/reddit/m/gold # subreddit showcasing new multireddits listing_chooser_explore_sr = +# historical cost to run a reddit server +pennies_per_server_second = 1970/1/1:1 diff --git a/r2/r2/lib/app_globals.py b/r2/r2/lib/app_globals.py index f5181c238..3ceb078d1 100755 --- a/r2/r2/lib/app_globals.py +++ b/r2/r2/lib/app_globals.py @@ -247,6 +247,9 @@ class Globals(object): 'sidebar_message', 'gold_sidebar_message', ], + ConfigValue.dict(ConfigValue.str, ConfigValue.float): [ + 'pennies_per_server_second', + ], } def __init__(self, global_conf, app_conf, paths, **extra): diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index 60e60dce3..55b4045f7 100755 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -26,10 +26,12 @@ from r2.lib.wrapped import Wrapped, Templated, CachedTemplate from r2.models import Account, FakeAccount, DefaultSR, make_feedurl from r2.models import FakeSubreddit, Subreddit, SubSR, AllMinus, AllSR from r2.models import Friends, All, Sub, NotFound, DomainSR, Random, Mod, RandomNSFW, RandomSubscription, MultiReddit, ModSR, Frontpage, LabeledMulti -from r2.models import Link, Printable, Trophy, bidding, PromoCampaign, PromotionWeights, Comment +from r2.models import Link, Printable, Trophy, PromoCampaign, PromotionWeights, Comment from r2.models import Flair, FlairTemplate, FlairTemplateBySubredditIndex from r2.models import USER_FLAIR, LINK_FLAIR from r2.models import GoldPartnerDealCode +from r2.models.bidding import Bid +from r2.models.gold import gold_payments_by_user from r2.models.promo import NO_TRANSACTION, PromotionLog, PromotedLinkRoadblock from r2.models.token import OAuth2Client, OAuth2AccessToken from r2.models import traffic @@ -74,6 +76,7 @@ from r2.lib.filters import safemarkdown from r2.lib.utils import Storage from babel.numbers import format_currency +from babel.dates import format_timedelta from collections import defaultdict import csv import cStringIO @@ -1603,6 +1606,12 @@ class ProfilePage(Reddit): elif c.user_is_sponsor: from admin_pages import SponsorSidebar rb.push(SponsorSidebar(self.user)) + + if c.user == self.user or c.user.employee: + seconds_bar = ServerSecondsBar(self.user) + if seconds_bar.message: + rb.push(seconds_bar) + rb.push(ProfileBar(self.user)) return rb @@ -1691,6 +1700,62 @@ class ProfileBar(Templated): self.my_fullname = c.user._fullname self.is_friend = self.user._id in c.user.friends + +class ServerSecondsBar(Templated): + pennies_per_server_second = { + datetime.datetime.strptime(datestr, "%Y/%m/%d").date(): v + for datestr, v in g.live_config['pennies_per_server_second'].iteritems() + } + + @classmethod + def get_rate(cls, dt): + cutoff_dates = sorted(cls.pennies_per_server_second.keys()) + dt = dt.date() + key = max(filter(lambda cutoff_date: dt >= cutoff_date, cutoff_dates)) + return cls.pennies_per_server_second[key] + + @classmethod + def subtract_fees(cls, pennies): + # for simplicity all payment processor fees are $0.30 + 2.9% + return pennies * (1 - 0.029) - 30 + + def __init__(self, user): + Templated.__init__(self) + + seconds = 0. + gold_payments = gold_payments_by_user(user) + + for payment in gold_payments: + rate = self.get_rate(payment.date) + seconds += self.subtract_fees(payment.pennies) / rate + + try: + q = (Bid.query().filter(Bid.account_id == user._id) + .filter(Bid.status == Bid.STATUS.CHARGE) + .filter(Bid.transaction > 0)) + selfserve_payments = list(q) + except NotFound: + selfserve_payments = [] + + for payment in selfserve_payments: + rate = self.get_rate(payment.date) + seconds += self.subtract_fees(payment.charge_amount * 100) / rate + + if not seconds: + self.message = '' + else: + delta = datetime.timedelta(seconds=seconds) + server_time = format_timedelta(delta, threshold=5, locale=c.locale) + + if user == c.user: + message = _("you have helped pay for %(time)s of reddit " + "server time.") + else: + message = _("%(user)s has helped pay for %%(time)s of reddit " + "server time.") % {'user': user.name} + self.message = message % {'time': server_time} + + class MenuArea(Templated): """Draws the gray box at the top of a page for sort menus""" def __init__(self, menus = []): @@ -3337,7 +3402,7 @@ class PromoteLinkForm(Templated): if c.user_is_sponsor: try: - bids = bidding.Bid.lookup(thing_id=link._id) + bids = Bid.lookup(thing_id=link._id) except NotFound: pass else: @@ -3345,7 +3410,7 @@ class PromoteLinkForm(Templated): bidders = Account._byID(set(bid.account_id for bid in bids), data=True, return_dict=True) for bid in bids: - status = bidding.Bid.STATUS.name[bid.status].lower() + status = Bid.STATUS.name[bid.status].lower() bidder = bidders[bid.account_id] row = Storage( status=status, diff --git a/r2/r2/public/static/css/reddit.less b/r2/r2/public/static/css/reddit.less index 72cd288b3..74474ffa6 100755 --- a/r2/r2/public/static/css/reddit.less +++ b/r2/r2/public/static/css/reddit.less @@ -6355,6 +6355,13 @@ body:not(.gold) .allminus-link { font-size: 16px; } +.server-seconds { + background-color: #EFF7FF; + border: 1px solid #5F99CF; + text-align: center; + padding: 10px; +} + .comment-visits-box .title { font-weight: bold; font-size: 12px; diff --git a/r2/r2/templates/serversecondsbar.html b/r2/r2/templates/serversecondsbar.html new file mode 100644 index 000000000..4eec0dbc9 --- /dev/null +++ b/r2/r2/templates/serversecondsbar.html @@ -0,0 +1,28 @@ +## 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-2013 +## reddit Inc. All Rights Reserved. +############################################################################### + +
+
+ ${thing.message} +
+
+