314 lines
9.9 KiB
Python
314 lines
9.9 KiB
Python
#!/srv/venv/bin/python
|
|
|
|
""" Process emails """
|
|
import sys
|
|
import os
|
|
PY3K = sys.version_info >= (3, 0)
|
|
|
|
import zipfile
|
|
from zipfile import BadZipFile
|
|
import re
|
|
import time
|
|
from time import strftime
|
|
|
|
import requests
|
|
import json
|
|
|
|
import io
|
|
|
|
from django.core.management.base import BaseCommand
|
|
from django_mailbox.models import Message, MessageAttachment,Mailbox
|
|
from django.urls import reverse
|
|
from django.conf import settings
|
|
|
|
from django.utils import timezone
|
|
from rowers.models import Workout, Rower
|
|
|
|
from rowingdata import rower as rrower
|
|
from rowingdata import rowingdata as rrdata
|
|
|
|
import rowers.uploads as uploads
|
|
from rowers.mailprocessing import make_new_workout_from_email, send_confirm
|
|
import rowers.polarstuff as polarstuff
|
|
import rowers.c2stuff as c2stuff
|
|
import rowers.rp3stuff as rp3stuff
|
|
import rowers.stravastuff as stravastuff
|
|
import rowers.nkstuff as nkstuff
|
|
from rowers.opaque import encoder
|
|
|
|
from rowers.models import User,VirtualRace,Workout
|
|
from rowers.plannedsessions import email_submit_race
|
|
from rowers.rower_rules import user_is_not_basic
|
|
|
|
|
|
# If you find a solution that does not need the two paths, please comment!
|
|
sys.path.append('$path_to_root_of_project$')
|
|
sys.path.append('$path_to_root_of_project$/$project_name$')
|
|
|
|
os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings'
|
|
|
|
if not getattr(__builtins__, "WindowsError", None):
|
|
class WindowsError(OSError): pass
|
|
|
|
def rdata(file_obj, rower=rrower()):
|
|
""" Read rowing data file and return 0 if file doesn't exist"""
|
|
try:
|
|
result = rrdata(file_obj, rower=rower)
|
|
except IOError:
|
|
result = 0
|
|
|
|
return result
|
|
|
|
def processattachment(rower, fileobj, title, uploadoptions,testing=False):
|
|
try:
|
|
filename = fileobj.name
|
|
# filename = os.path.abspath(fileobj.name)
|
|
except AttributeError:
|
|
filename = fileobj[6:]
|
|
|
|
|
|
# test if file exists and is not empty
|
|
try:
|
|
with io.open('media/'+filename,'rb') as fop:
|
|
line = fop.readline()
|
|
except (IOError, UnicodeEncodeError):
|
|
return 0
|
|
|
|
|
|
# set user
|
|
if rower.user.is_staff and 'username' in uploadoptions:
|
|
users = User.objects.filter(username=uploadoptions['username'])
|
|
if len(users)==1:
|
|
therower = users[0].rower
|
|
elif uploadoptions['username'] == '':
|
|
therower = rower
|
|
else:
|
|
return 0
|
|
else:
|
|
therower = rower
|
|
|
|
|
|
uploadoptions['secret'] = settings.UPLOAD_SERVICE_SECRET
|
|
uploadoptions['user'] = therower.user.id
|
|
uploadoptions['file'] = 'media/'+filename
|
|
uploadoptions['title'] = title
|
|
|
|
url = settings.UPLOAD_SERVICE_URL
|
|
if not testing:
|
|
response = requests.post(url,data=uploadoptions)
|
|
# print("Upload response status code",response.status_code, response.json())
|
|
if response.status_code == 200:
|
|
response_json = response.json()
|
|
workoutid = [int(response_json['id'])]
|
|
else:
|
|
workoutid = [0]
|
|
|
|
# this is ugly and needs to be done better
|
|
if testing:
|
|
workoutid = [
|
|
make_new_workout_from_email(therower, filename, title,testing=testing)
|
|
]
|
|
if workoutid[0] and uploadoptions and not 'error' in uploadoptions:
|
|
workout = Workout.objects.get(id=workoutid[0])
|
|
uploads.make_private(workout, uploadoptions)
|
|
uploads.set_workouttype(workout, uploadoptions)
|
|
uploads.do_sync(workout, uploadoptions)
|
|
|
|
|
|
if 'raceid' in uploadoptions and workoutid[0] and rower.user.is_staff:
|
|
if testing and workoutid[0]:
|
|
w = Workout.objects.get(id = workoutid[0])
|
|
w.startdatetime = timezone.now()
|
|
w.date = timezone.now().date()
|
|
w.save()
|
|
try:
|
|
race = VirtualRace.objects.get(id=uploadoptions['raceid'])
|
|
if race.manager == rower.user:
|
|
result = email_submit_race(therower,race,workoutid[0])
|
|
except VirtualRace.DoesNotExist:
|
|
pass
|
|
|
|
|
|
return workoutid
|
|
|
|
def get_from_address(message):
|
|
|
|
from_address = message.from_address[0].lower()
|
|
|
|
if message.encoded:
|
|
body = message.text.splitlines()
|
|
else:
|
|
body = message.get_body().splitlines()
|
|
|
|
try:
|
|
first_line = body[0].lower()
|
|
except IndexError:
|
|
first_line = ''
|
|
|
|
try:
|
|
first_line = first_line.decode('utf-8')
|
|
except AttributeError:
|
|
pass
|
|
|
|
if "quiske" in first_line:
|
|
match = re.search(r'[\w\.-]+@[\w\.-]+', first_line)
|
|
return match.group(0)
|
|
|
|
return from_address
|
|
|
|
|
|
class Command(BaseCommand):
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
'--testing',
|
|
action='store_true',
|
|
dest='testing',
|
|
default=False,
|
|
help="Run in testing mode, don't send emails",
|
|
)
|
|
parser.add_argument(
|
|
'--mailbox',
|
|
action='store_true',
|
|
dest='mailbox',
|
|
default='workouts',
|
|
help="Changing mailbox name",
|
|
)
|
|
|
|
"""Run the Email processing command """
|
|
def handle(self, *args, **options):
|
|
if 'testing' in options:
|
|
testing = options['testing']
|
|
else:
|
|
testing = False
|
|
|
|
if 'mailbox' in options:
|
|
workoutmailbox = Mailbox.objects.get(name=options['mailbox'])
|
|
else:
|
|
workoutmailbox = Mailbox.objects.get(name='workouts')
|
|
|
|
if 'failedmailbox' in options:
|
|
failedmailbox = Mailbox.objects.get(name=options['failedmailbox'])
|
|
else:
|
|
failedmailbox = Mailbox.objects.get(name='Failed')
|
|
|
|
# Polar
|
|
polar_available = polarstuff.get_polar_notifications()
|
|
res = polarstuff.get_all_new_workouts(polar_available)
|
|
|
|
# Concept2
|
|
rowers = Rower.objects.filter(c2_auto_import=True)
|
|
for r in rowers:
|
|
if user_is_not_basic(r.user):
|
|
c2stuff.get_c2_workouts(r)
|
|
|
|
rowers = Rower.objects.filter(rp3_auto_import=True)
|
|
for r in rowers:
|
|
if user_is_not_basic(r.user):
|
|
res = rp3stuff.get_rp3_workouts(r)
|
|
|
|
rowers = Rower.objects.filter(nk_auto_import=True)
|
|
for r in rowers:
|
|
if user_is_not_basic(r.user):
|
|
res = nkstuff.get_nk_workouts(r)
|
|
|
|
messages = Message.objects.filter(mailbox_id = workoutmailbox.id)
|
|
message_ids = [m.id for m in messages]
|
|
attachments = MessageAttachment.objects.filter(
|
|
message_id__in=message_ids
|
|
)
|
|
cntr = 0
|
|
for attachment in attachments:
|
|
filename, extension = os.path.splitext(attachment.document.name)
|
|
extension = extension.lower()
|
|
# extension = attachment.document.name[-3:].lower()
|
|
try:
|
|
message = Message.objects.get(id=attachment.message_id)
|
|
if message.encoded:
|
|
# if message.text:
|
|
body = "\n".join(message.text.splitlines())
|
|
else:
|
|
body = message.get_body()
|
|
|
|
uploadoptions = uploads.upload_options(body)
|
|
|
|
from_address = get_from_address(message)
|
|
|
|
name = message.subject
|
|
# get a list of users
|
|
# theusers = User.objects.filter(email=from_address)
|
|
rowers = [
|
|
r for r in Rower.objects.all() if r.user.email.lower() == from_address
|
|
]
|
|
try:
|
|
rowers2 = [
|
|
r for r in Rower.objects.all() if from_address in r.emailalternatives
|
|
]
|
|
rowers = rowers+rowers2
|
|
except TypeError:
|
|
pass
|
|
except IOError:
|
|
rowers = []
|
|
except Message.DoesNotExist:
|
|
try:
|
|
attachment.delete()
|
|
except:
|
|
pass
|
|
for rower in rowers:
|
|
if 'zip' in extension:
|
|
try:
|
|
zip_file = zipfile.ZipFile(attachment.document)
|
|
for id,filename in enumerate(zip_file.namelist()):
|
|
datafile = zip_file.extract(
|
|
filename, path='media/')
|
|
if id>0:
|
|
title = name+' ('+str(id+1)+')'
|
|
else:
|
|
title = name
|
|
workoutid = processattachment(
|
|
rower, datafile, title, uploadoptions,
|
|
testing=testing
|
|
)
|
|
except BadZipFile:
|
|
pass
|
|
|
|
else:
|
|
# move attachment and make workout
|
|
|
|
workoutid = processattachment(
|
|
rower, attachment.document, name, uploadoptions,
|
|
testing=testing
|
|
)
|
|
|
|
# We're done with the attachment. It can be deleted
|
|
try:
|
|
attachment.delete()
|
|
except IOError:
|
|
pass
|
|
except WindowsError:
|
|
if not testing:
|
|
time.sleep(2)
|
|
try:
|
|
attachment.delete()
|
|
except WindowsError:
|
|
pass
|
|
except:
|
|
message.mailbox = failedmailbox
|
|
message.save()
|
|
|
|
if message.attachments.exists() is False:
|
|
# no attachments, so can be deleted
|
|
message.delete()
|
|
|
|
messages = Message.objects.all()
|
|
for message in messages:
|
|
if message.attachments.exists() is False:
|
|
message.delete()
|
|
|
|
# Strava
|
|
#rowers = Rower.objects.filter(strava_auto_import=True)
|
|
#for r in rowers:
|
|
# stravastuff.get_strava_workouts(r)
|
|
|
|
self.stdout.write(self.style.SUCCESS(
|
|
'Successfully processed email attachments'))
|