diff --git a/mlmanager.py b/mlmanager.py
index f4e0102..0e3ed85 100644
--- a/mlmanager.py
+++ b/mlmanager.py
@@ -8,21 +8,62 @@
#
# Leonardo Robol <leo@robol.it>
-__author__ = "Leonardo Robol <leo@robol.it>"
+#
+# START OF CONFIGURATION SECTION
+#
+
+# The fully qualified (or not fully qualified - it really doesn't matter)
+# domain that the server is part of.
+local_domain = "robol.it"
+
+# This is the mail address that will be set as sender for all
+# the emails generated by the script.
+from_addr = "mldonkey <mldonkey@%s>" % local_domain
-import os, sys, socket, shutil, subprocess, time
+# Mail server that the script will use to deliver emails. It must be properly
+# configured to relay mail from the domain selected.
+mail_server = "localhost"
-# Set file extensions to match.
-video_extensions = ['avi', 'mpeg', 'mpg', 'mkv', 'm2v', 'divx', 'xvid']
-audio_extensions = ['mp3,' 'ogg', 'wav', 'flac', 'aac' ]
-text_extensions = ['pdf', 'doc', 'odt', 'ods', 'odp', 'ppt', 'rtf',
- 'pps', 'xls' , 'txt' ]
+# Users that should be notified when an error occurs in the script. You
+# can use the wildcard "owner" to match the owner of the file downladed.
+# This is generally true for every email function in mlmanager
+error_recipients = [ "owner" ]
+
+# Number of times that rsync should try to transfer the file before
+# giving up.
+rsync_tries = 5
+
+# Set file extensions to match. You can add extensions in every category
+video_extensions = ['avi', 'mpeg', 'mpg', 'mkv', 'm2v', 'divx', 'xvid']
+audio_extensions = ['mp3,' 'ogg', 'wav', 'flac', 'aac' ]
+text_extensions = ['pdf', 'doc', 'odt', 'ods', 'odp', 'ppt', 'rtf',
+ 'pps', 'xls' , 'txt' ]
cdimage_extensions = [ 'iso', 'nrg' ]
+archive_extensions = [ 'rar', 'zip', '7z', 'tar.gz', 'tar.bz2', 'lzo' ]
+
+
+#
+# END OF CONFIGURATION
+#
+#
+# START OF CODE
+#
+
+__author__ = "Leonardo Robol <leo@robol.it>"
+
+import os, sys, socket, shutil, subprocess, time, smtplib
+from email.mime.text import MIMEText
class FileType():
"""
This class represent the type of a file, i.e you
can check if it is a video, a text, an image...
+ It can be:
+ - video
+ - audio
+ - text
+ - archive
+ - other
"""
def __init__(self, filename):
@@ -44,6 +85,8 @@ class FileType():
self._type = "text"
elif len(filter(self._test_extension, cdimage_extensions)) > 0:
self._type = "cdimage"
+ elif len(filter(self._test_extension, archive_extensions)) > 0:
+ self._type = "archive"
else:
self._type = "other"
@@ -59,6 +102,9 @@ class FileType():
def is_cdimage(self):
return (self._type == "cdimage")
+ def is_archive(self):
+ return (self._type == "archive")
+
def __str__(self):
return self._type
@@ -101,6 +147,8 @@ class Download():
self._owner = os.getenv("FILE_OWNER")
self._incoming = os.getenv("INCOMING")
+ self._user_email = os.getenv("USER_EMAIL")
+
# The file is not yet committed. You will need to commit it
# before trying to move it.
self._committed = False
@@ -114,6 +162,7 @@ class Download():
self._type = FileType(self._filename)
+
def __repr__(self):
return "<Download '%s'>" % self._filename
@@ -131,6 +180,7 @@ class Download():
self._committed = True
+
def send_command(self, command_list):
"""You can send a command, or a list of command
to the daemon. Note that the every call to this
@@ -145,7 +195,7 @@ class Download():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 4000))
except Exception, e:
- raise RuntimeError("Unable to connect to mldonkey daemon: %s" % e)
+ self.notify_error("Unable to connect to mldonkey daemon: %s" % e)
# Costruct the command line
command_line = "\n".join(command_list)
@@ -177,6 +227,19 @@ class Download():
# Update _dest_path
self._dest_path = destination_folder + filename
+ def copy(self, destination, track = False):
+ """
+ Copy the file to another destination. Destination could be a folder
+ to move the file in, or a complete path. The script will keep track
+ only of the original file, i.e. if you call move() it will move the
+ original file; if this is not what you want, move() the file to the
+ right location and then copy() it around."""
+
+ if not self._committed:
+ self.commit()
+ shutil.copy(self._dest_path, destination)
+
+
def rsync(self, remote_destination):
"""Rsync the file to the remote destination. There must be an ssh key
in the remote server otherwise nothing will happen. The script will
@@ -188,32 +251,69 @@ class Download():
# Initialize internal counter of the times we have tried to move the file
self._rsync_counter = 0
s = subprocess.Popen("rsync --partial -az --compress-level=9 \"%s\" \"%s\"" % (self._dest_path,
- remote_destination),
- shell = True, stderr = subprocess.PIPE, stdout = subprocess.PIPE)
+ remote_destination),
+ shell = True, stderr = subprocess.PIPE, stdout = subprocess.PIPE)
ret_code = s.wait ()
- # If we fail call this funtion recursively to retry...wait for 5 seconds and the go (it could
+ # If we fail call this funtion recursively to retry...wait for 60 seconds and then go (it could
# be only a network problem)
if ret_code != 0:
self._rsync_counter += 1
- if self._rsync_counter < 5:
- time.sleep (5)
+ if self._rsync_counter < rsync_tries:
+ time.sleep (60)
self.rsync(remote_destination)
else:
self.notify_error("Rsync transfer of file %s failed more than 5 times, aborting" % self._filename)
def notify_error(self, message):
"""Notify error via email"""
- pass
+ self._send_mail (error_recipients, "[mlmanager] An error occurred",
+ message)
- def notify_email(self, recipients, message):
+ def notify_email(self, recipients, subject, message):
"""Notify something to some people via email"""
- pass
+ self._send_email (recipients, subject, message)
+
+ def _send_email(self, recipients, subject, message):
+ """Low level function to send an e-mail."""
+
+ msg = MIMEText(message)
+ msg.set_charset ("utf-8")
+ msg['From'] = from_addr
+
+ # If recipients is a string make it a list
+ if isinstance(recipients, str):
+ recipients = [ recipients ]
+
+ # Add user email if requested
+ if "owner" in recipients:
+ recipients.remove("owner")
+ recipients.append(self._user_email)
+
+ msg['To'] = ", ".join(to_addr)
+ msg['Subject'] = subject
+
+ # Obtain message data
+ data = msg.as_string ()
+
+ # Open a connection to the SMTP server
+ try:
+ s = smtplib.SMTP( host = mail_server )
+ s.sendmail (from_addr, to_addr, data)
+ s.quit ()
+ except Exception, e:
+ raise RuntimeError("Error while notifying you of an error: %s" % e)
+
+ def is_in_group(self, group):
+ """Return True if file is part of the selected group,
+ False otherwise"""
+ return (self._group == group)
+
def get_type(self):
"""
Return the type of the selected file, it could be
- Video, Audio, Image or Other, if none matches.
+ video, audio, image, cdimage, archive or other, if none matches.
"""
return str(self._type)