adding a reporting module

This commit is contained in:
Jeremy Edberg
2008-09-10 16:54:08 -07:00
parent 886ceb2a88
commit 8fe2e576dc

View 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