mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-27 15:58:06 -05:00
adding a reporting module
This commit is contained in:
166
r2/r2/lib/utils/reporting.py
Normal file
166
r2/r2/lib/utils/reporting.py
Normal file
@@ -0,0 +1,166 @@
|
||||
import sqlalchemy as sa
|
||||
import datetime as dt
|
||||
import time
|
||||
import smtplib
|
||||
|
||||
from r2.lib.utils import timeago
|
||||
from r2.lib.db import tdb_sql
|
||||
from r2.models.mail_queue import Email
|
||||
|
||||
class Report(object):
|
||||
"""Class for creating reports based on reddit data"""
|
||||
def __init__(self, period=None, date=None):
|
||||
"""Sets up the date storage."""
|
||||
self.period = period
|
||||
self.date = date
|
||||
|
||||
def append_date_clause(self, table, select, all_time=None):
|
||||
"""Create the date portion of a where clause based on the time
|
||||
period specified."""
|
||||
if all_time:
|
||||
return select
|
||||
if self.period and not self.date:
|
||||
select.append_whereclause(table.c.date > timeago(self.period))
|
||||
if self.date:
|
||||
seconds = 24 * 60 * 60
|
||||
wheredate = dt.datetime.strptime(self.date,"%Y%m%d")
|
||||
select.append_whereclause(table.c.date >= wheredate)
|
||||
select.append_whereclause((table.c.date < wheredate
|
||||
+ dt.timedelta(0, seconds)))
|
||||
return select
|
||||
|
||||
def total_things(self, table_name, spam=None, all_time=None):
|
||||
"""Return totals based on items in the thing tables."""
|
||||
t = tdb_sql.types_name[table_name]['thing_table']
|
||||
s = sa.select([sa.func.count(t.c.thing_id)])
|
||||
if spam:
|
||||
s.append_whereclause(t.c.spam==spam)
|
||||
s.append_whereclause(t.c.deleted=='f')
|
||||
s = self.append_date_clause(t, s, all_time=all_time)
|
||||
|
||||
return s.execute().fetchone()[0]
|
||||
|
||||
def total_relation(self, table_name, key, value=None, all_time=None):
|
||||
"""Return totals based on relationship data."""
|
||||
rel_table = tdb_sql.rel_types_name['%s_account_link' % table_name].rel_table
|
||||
t1, t2 = rel_table[0], rel_table[3]
|
||||
|
||||
s = sa.select([sa.func.count(t1.c.date)],
|
||||
sa.and_(t1.c.rel_id == t2.c.thing_id, t2.c.key == key))
|
||||
if value:
|
||||
s.append_whereclause(t2.c.value == value)
|
||||
s = self.append_date_clause(t1, s, all_time=all_time)
|
||||
return s.execute().fetchone()[0]
|
||||
|
||||
def email_stats(self, table_name, all_time=None):
|
||||
"""Calculate stats based on the email tables."""
|
||||
t = getattr(Email.handler, '%s_table' % table_name)
|
||||
s = sa.select([sa.func.count(t.c.kind)])
|
||||
s = self.append_date_clause(t, s, all_time=all_time)
|
||||
return s.execute().fetchone()[0]
|
||||
|
||||
def css_stats(self, val, all_time=None):
|
||||
"""Create stats related to custom css and headers."""
|
||||
t = tdb_sql.types_name['subreddit'].data_table[0]
|
||||
s = sa.select([sa.func.count(t.c.key)], t.c.key == val)
|
||||
return s.execute().fetchone()[0]
|
||||
|
||||
|
||||
class TextReport(object):
|
||||
"""Class for building text based reports"""
|
||||
def __init__(self, period, date):
|
||||
self.r = Report(period=period, date=date)
|
||||
self.rep = ''
|
||||
self.period = period
|
||||
self.date = date
|
||||
if period:
|
||||
self.phrase = "in the last"
|
||||
self.time = period
|
||||
if date:
|
||||
self.phrase = "on"
|
||||
self.time = self.pretty_date(date)
|
||||
|
||||
def _thing_stats(self, thing, all_time=None):
|
||||
"""return a header and a list of thing stats"""
|
||||
header = "%ss created " % thing
|
||||
if all_time:
|
||||
header += "since the beginning:"
|
||||
else:
|
||||
header += "%s %s:" % (self.phrase, self.time)
|
||||
columns = ['all', 'spam', 'non-spam']
|
||||
data = [str(self.r.total_things(thing, all_time=all_time)),
|
||||
str(self.r.total_things(thing, spam="t", all_time=all_time)),
|
||||
str(self.r.total_things(thing, spam="f", all_time=all_time))]
|
||||
return [[header], columns, data]
|
||||
|
||||
def pretty_date(self, date):
|
||||
"""Makes a pretty date from a date"""
|
||||
return time.strftime("%a, %b %d, %Y", time.strptime(date,"%Y%m%d"))
|
||||
|
||||
def process_things(self, things, all_time=None):
|
||||
"""builds a report for a list of things"""
|
||||
ret = ''
|
||||
for thing in things:
|
||||
(header, columns, data) = self._thing_stats(thing, all_time=all_time)
|
||||
ret += '\n'.join(['\t'.join(header), '\t'.join(columns), '\t'.join(data)])
|
||||
ret += '\n'
|
||||
return ret
|
||||
|
||||
def process_relation(self, name, table_name, key, value, all_time=None):
|
||||
"""build a report for a relation"""
|
||||
ret = ("%d\tTotal %s %s %s\n" %
|
||||
(self.r.total_relation(table_name, key, value=value, all_time=all_time),
|
||||
name, self.phrase, self.time))
|
||||
return ret
|
||||
|
||||
def process_other(self, type, name, table_name, all_time=None):
|
||||
"""build other types of reports"""
|
||||
if type == 'email':
|
||||
f = self.r.email_stats
|
||||
if type == 'css':
|
||||
f = self.r.css_stats
|
||||
ret = ("%d\tTotal %s %s %s\n" %
|
||||
(f(table_name, all_time=all_time), name, self.phrase, self.time))
|
||||
return ret
|
||||
|
||||
def build(self, show_all_time=True):
|
||||
"""build a complete text report"""
|
||||
rep = 'Subject: reddit stats %s %s\n\n' % (self.phrase, self.time)
|
||||
|
||||
rep += self.process_things(['account','subreddit','link','message','comment'])
|
||||
|
||||
rep += "\n"
|
||||
rep += self.process_relation('valid votes', 'vote', 'valid_thing', 't')
|
||||
rep += self.process_relation('organic votes', 'vote', 'organic', 't')
|
||||
rep += self.process_relation('votes', 'vote', 'valid_thing', None)
|
||||
rep += self.process_relation('reports', 'report', 'amount', None)
|
||||
|
||||
rep += self.process_other('email', 'share emails sent', 'track')
|
||||
rep += self.process_other('email', 'share emails rejected', 'reject')
|
||||
|
||||
if show_all_time:
|
||||
rep += self.process_other('css', 'subreddits with custom css',
|
||||
'stylesheet_hash', all_time=True)
|
||||
rep += self.process_other('css', 'subreddits with a custom header',
|
||||
'header', all_time=True)
|
||||
rep += "\n"
|
||||
rep += self.process_things(['account','subreddit','link','message','comment'],
|
||||
all_time=True)
|
||||
|
||||
return rep
|
||||
|
||||
def yesterday():
|
||||
"""return yesterday's date"""
|
||||
return "%04d%02d%02d" % time.localtime(time.time() - 60*60*24)[0:3]
|
||||
|
||||
def run(period=None, date=None, show_all_time=True,
|
||||
sender=None, recipients=None, smtpserver=None):
|
||||
if not date and not period:
|
||||
date = yesterday()
|
||||
session = smtplib.SMTP(smtpserver)
|
||||
report = TextReport(period, date).build(show_all_time=show_all_time)
|
||||
if sender:
|
||||
report = "To: %s\n" % ', '.join(recipients) + report
|
||||
smtpresult = session.sendmail(sender, recipients, report)
|
||||
else:
|
||||
print report
|
||||
Reference in New Issue
Block a user