From f7ab21560d941565b5331cefd227faaac7e66b13 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 22 Oct 2017 13:01:16 +0200 Subject: [PATCH] refactored, not tested --- rowers/mailprocessing.py | 151 +++------------------ rowers/management/commands/processemail.py | 130 +++++++----------- 2 files changed, 69 insertions(+), 212 deletions(-) diff --git a/rowers/mailprocessing.py b/rowers/mailprocessing.py index df6760c7..db3bccd0 100644 --- a/rowers/mailprocessing.py +++ b/rowers/mailprocessing.py @@ -1,24 +1,19 @@ # Processes emails sent to workouts@rowsandall.com +""" Processes emails sent to workouts@rowsandall.com """ +import shutil import time from django.conf import settings from rowers.tasks import handle_sendemail_unrecognized -from django_mailbox.models import Mailbox, Message, MessageAttachment -from rowers.models import Workout, User, Rower, WorkoutForm, RowerForm, GraphImage, AdvancedWorkoutForm -from django.core.files.base import ContentFile -from django.core.mail import send_mail, BadHeaderError, EmailMessage -from rowsandall_app.settings import BASE_DIR +from django_mailbox.models import Message, MessageAttachment +from rowers.models import User, Rower, RowerForm + +from django.core.mail import EmailMessage from rowingdata import rower as rrower -from rowingdata import main as rmain -from rowingdata import rowingdata as rrdata -from rowingdata import TCXParser, RowProParser, ErgDataParser -from rowingdata import MysteryParser, BoatCoachParser -from rowingdata import painsledDesktopParser, speedcoachParser, ErgStickParser -from rowingdata import SpeedCoach2Parser, FITParser, fitsummarydata -from rowingdata import make_cumvalues -from rowingdata import summarydata, get_file_type -from scipy.signal import savgol_filter +from rowingdata import rowingdata as rrdata + +from rowingdata import get_file_type import zipfile import os @@ -33,6 +28,7 @@ queuehigh = django_rq.get_queue('default') def send_confirm(u, name, link, options): + """ Send confirmation email to user when email has been processed """ fullemail = u.email subject = 'Workout added: ' + name message = 'Dear ' + u.first_name + ',\n\n' @@ -55,6 +51,7 @@ def send_confirm(u, name, link, options): def rdata(file, rower=rrower()): + """ Reads rowingdata data or returns 0 on Error """ try: res = rrdata(file, rower=rower) except IOError: @@ -65,119 +62,10 @@ def rdata(file, rower=rrower()): return res -# Some error protection around process attachments - - -def safeprocessattachments(): - try: - return processattachments() - except: - return [0] - -# This is duplicated in management/commands/processemail -# Need to double check the code there, update here, and only -# use the code here. - - -def processattachments(): - # in res, we store the ids of the new workouts - res = [] - attachments = MessageAttachment.objects.all() - for a in attachments: - donotdelete = 0 - m = Message.objects.get(id=a.message_id) - from_address = m.from_address[0] - name = m.subject - - # get a list of users - theusers = User.objects.filter(email=from_address) - for u in theusers: - try: - rr = Rower.objects.get(user=u.id) - # move attachment and make workout - try: - wid = [make_new_workout_from_email(rr, a.document, name)] - res += wid - link = 'https://rowsandall.com/rowers/workout/' + \ - str(wid[0]) + '/edit' - if wid != 1: - dd = send_confirm(u, name, link) - except: - # replace with code to process error - res += ['fail: ' + name] - donotdelete = 1 - except Rower.DoesNotExist: - pass - - # remove attachment - if donotdelete == 0: - a.delete() - - if m.attachments.exists() == False: - # no attachments, so can be deleted - m.delete() - - # Delete remaining messages (which should not have attachments) - mm = Message.objects.all() - for m in mm: - if m.attachments.exists() == False: - m.delete() - - return res - -# As above, but with some print commands for debugging purposes - - -def processattachments_debug(): - res = [] - attachments = MessageAttachment.objects.all() - for a in attachments: - donotdelete = 1 - m = Message.objects.get(id=a.message_id) - from_address = m.from_address[0] - name = m.subject - - # get a list of users - theusers = User.objects.filter(email=from_address) - print theusers - for u in theusers: - try: - rr = Rower.objects.get(user=u.id) - doorgaan = 1 - except: - doorgaan = 0 - if doorgaan: - # move attachment and make workout - print a.document - print name - wid = [make_new_workout_from_email(rr, a.document, name)] - res += wid - link = 'https://rowsandall.com/rowers/workout/' + \ - str(wid[0]) + '/edit' - if wid != 1: - dd = send_confirm(u, name, link) - - # remove attachment - if donotdelete == 0: - a.delete() - - if m.attachments.exists() == False: - # no attachments, so can be deleted - m.delete() - - mm = Message.objects.all() - for m in mm: - if m.attachments.exists() == False: - m.delete() - - return res - -# Process the attachment file, create new workout -# The code here is duplication of the code in views.py (workout_upload_view) -# Need to move the code to a subroutine used both in views.py and here def make_new_workout_from_email(rr, f2, name, cntr=0): + """ This one is used in processemail """ workouttype = 'rower' try: @@ -196,15 +84,18 @@ def make_new_workout_from_email(rr, f2, name, cntr=0): fileformat = fileformat[2] if fileformat == 'unknown': + fcopy = "copy_of_"+f2 + with open(f2, 'r') as f_in, open(fcopy, 'w') as f_out: + shutil.copyfileobj(f_in,f_out) if settings.DEBUG: - res = handle_sendemail_unrecognized.delay(f2, + res = handle_sendemail_unrecognized.delay(fcopy, "roosendaalsander@gmail.com") else: res = queuehigh.enqueue(handle_sendemail_unrecognized, - f2, "roosendaalsander@gmail.com") + fcopy, "roosendaalsander@gmail.com") - return 1 + return 0 summary = '' # handle non-Painsled @@ -216,11 +107,7 @@ def make_new_workout_from_email(rr, f2, name, cntr=0): inboard = 0.88 oarlength = 2.89 - # make workout and put in database - # r = rrower(hrmax=rr.max,hrut2=rr.ut2, - # hrut1=rr.ut1,hrat=rr.at, - # hrtr=rr.tr,hran=rr.an,ftp=r.ftp) - row = rdata(f3) # ,rower=r) + row = rdata(f3) if row == 0: return 0 diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 0a7cf1ca..db17b354 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -5,22 +5,19 @@ import os import zipfile -from django.core.management.base import BaseCommand - import time from time import strftime -from django.conf import settings +from django.core.management.base import BaseCommand from django_mailbox.models import Message, MessageAttachment from rowers.models import Workout, Rower from rowingdata import rower as rrower - from rowingdata import rowingdata as rrdata -from rowers.mailprocessing import make_new_workout_from_email, send_confirm import rowers.uploads as uploads +from rowers.mailprocessing import make_new_workout_from_email, send_confirm # If you find a solution that does not need the two paths, please comment! sys.path.append('$path_to_root_of_project$') @@ -28,15 +25,58 @@ sys.path.append('$path_to_root_of_project$/$project_name$') os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' -def rdata(file, rower=rrower()): +def rdata(file_obj, rower=rrower()): """ Read rowing data file and return 0 if file doesn't exist""" try: - res = rrdata(file, rower=rower) + res = rrdata(file_obj, rower=rower) except IOError: res = 0 return res +def processattachment(rr, f2, title, uploadoptions): + wid = [ + make_new_workout_from_email(rr, f2[6:], title) + ] + if wid: + res += wid + link = 'http://rowsandall.com/rowers/workout/' + \ + str(wid[0]) + '/edit' + if uploadoptions and not 'error' in uploadoptions: + w = Workout.objects.get(id=wid[0]) + r = w.user + uploads.do_sync(w, uploadoptions) + uploads.make_private(w, uploadoptions) + if 'make_plot' in uploadoptions: + plottype = uploadoptions['plottype'] + f1 = w.csvfilename[6:-4] + timestr = strftime("%Y%m%d-%H%M%S") + imagename = f1 + timestr + '.png' + resu = uploads.make_plot( + r, w, f1, + w.csvfilename, + plottype, name, + imagename=imagename + ) + try: + if wid: + dd = send_confirm( + rr.user, title, link, + uploadoptions + ) + time.sleep(10) + except: + try: + time.sleep(10) + if wid: + dd = send_confirm( + rr.user, title, link, + uploadoptions + ) + except: + pass + + return wid class Command(BaseCommand): """Run the Email processing command """ @@ -46,7 +86,6 @@ class Command(BaseCommand): cntr = 0 for a in attachments: extension = a.document.name[-3:].lower() - donotdelete = 0 m = Message.objects.get(id=a.message_id) body = "\n".join(m.text.splitlines()) uploadoptions = uploads.upload_options(body) @@ -64,85 +103,16 @@ class Command(BaseCommand): for f in z.namelist(): f2 = z.extract(f, path='media/') title = os.path.basename(f2) - wid = [ - make_new_workout_from_email(rr, f2[6:], title) - ] - res += wid - link = 'http://rowsandall.com/rowers/workout/' + \ - str(wid[0]) + '/edit' - if uploadoptions and not 'error' in uploadoptions: - w = Workout.objects.get(id=wid[0]) - r = w.user - uploads.do_sync(w, uploadoptions) - uploads.make_private(w, uploadoptions) - if 'make_plot' in uploadoptions: - plottype = uploadoptions['plottype'] - f1 = w.csvfilename[6:-4] - timestr = strftime("%Y%m%d-%H%M%S") - imagename = f1 + timestr + '.png' - resu = uploads.make_plot(r, w, f1, - w.csvfilename, - plottype, name, - imagename=imagename) - try: - if wid != 1: - dd = send_confirm(rr.user, title, link, - uploadoptions) - time.sleep(10) - except: - try: - time.sleep(10) - if wid != 1: - dd = send_confirm(rr.user, title, link, - uploadoptions) - except: - pass - + wid = processattachment(rr, f2, title, uploadoptions) else: # move attachment and make workout - try: - wid = [ - make_new_workout_from_email(rr, - a.document, - name) - ] - res += wid - link = 'http://rowsandall.com/rowers/workout/' + \ - str(wid[0]) + '/edit' - if uploadoptions: - w = Workout.objects.get(id=wid[0]) - r = w.user - uploads.do_sync(w, uploadoptions) - uploads.make_private(w, uploadoptions) - if 'make_plot' in uploadoptions: - plottype = uploadoptions['plottype'] - f1 = w.csvfilename[6:-4] - timestr = strftime("%Y%m%d-%H%M%S") - imagename = f1 + timestr + '.png' - resu = uploads.make_plot(r, w, f1, - w.csvfilename, - plottype, name, - imagename=imagename) - - except: - # replace with code to process error - res += ['fail: ' + name] - donotdelete = 1 - wid = 1 - try: - if wid != 1: - dd = send_confirm(rr.user, name, link, - uploadoptions) - time.sleep(10) - except: - pass + wid = processattachment(rr, a.document, name, uploadoptions) + # We're done with the attachment. It can be deleted try: a.delete() except IOError: pass - # remove attachment - # if donotdelete == 0: if m.attachments.exists() is False: # no attachments, so can be deleted