Update the Notifications and FreeSpace plugins descriptions.
On the Notifications plugin, moved the Core and GtkUi notification implementations to `core.py` and `gtkui.py` respectively.
This commit is contained in:
parent
127b577440
commit
7812f7b4e4
|
@ -77,7 +77,7 @@ class Core(CorePluginBase):
|
|||
self._timer = task.LoopingCall(self.update)
|
||||
else:
|
||||
self._timer.stop()
|
||||
self._interval = 15 #60
|
||||
self._interval = 60 * 5 # every 5 minutes
|
||||
if self.config['enabled']:
|
||||
self._timer.start(self._interval, False)
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
|
@ -45,8 +45,8 @@ __author_email__ = "ufs@ufsoft.org"
|
|||
__version__ = "0.1"
|
||||
__url__ = "http://deluge.ufsoft.org/hg/Notification/"
|
||||
__license__ = "GPLv3"
|
||||
__description__ = ""
|
||||
__long_description__ = """"""
|
||||
__description__ = "Plugin which continuously checks for available free space."
|
||||
__long_description__ = __description__
|
||||
__pkg_data__ = {__plugin_name__.lower(): ["template/*", "data/*"]}
|
||||
|
||||
setup(
|
||||
|
@ -67,7 +67,5 @@ setup(
|
|||
%s = %s:CorePlugin
|
||||
[deluge.plugin.gtkui]
|
||||
%s = %s:GtkUIPlugin
|
||||
[deluge.plugin.webui]
|
||||
%s = %s:WebUIPlugin
|
||||
""" % ((__plugin_name__, __plugin_name__.lower())*3)
|
||||
""" % ((__plugin_name__, __plugin_name__.lower())*2)
|
||||
)
|
||||
|
|
|
@ -37,12 +37,9 @@
|
|||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
|
||||
import smtplib
|
||||
from twisted.internet import defer, threads
|
||||
from twisted.internet import defer
|
||||
from deluge import component
|
||||
from deluge.log import LOG as log
|
||||
from deluge.ui.client import client
|
||||
import deluge.common
|
||||
|
||||
try:
|
||||
from deluge.event import known_events
|
||||
|
@ -50,20 +47,6 @@ except ImportError:
|
|||
# Old deluge version
|
||||
known_events = {}
|
||||
|
||||
try:
|
||||
import pygame
|
||||
SOUND_AVAILABLE = True
|
||||
except ImportError:
|
||||
SOUND_AVAILABLE = False
|
||||
|
||||
try:
|
||||
import pynotify
|
||||
POPUP_AVAILABLE = True
|
||||
if deluge.common.windows_check():
|
||||
POPUP_AVAILABLE = False
|
||||
except ImportError:
|
||||
POPUP_AVAILABLE = False
|
||||
|
||||
|
||||
def get_resource(filename):
|
||||
import pkg_resources, os
|
||||
|
@ -154,304 +137,3 @@ class CustomNotifications(object):
|
|||
log.debug("Notification failure using %s: %s", kind, failure)
|
||||
return failure
|
||||
|
||||
|
||||
class CoreNotifications(CustomNotifications):
|
||||
|
||||
def enable(self):
|
||||
CustomNotifications.enable(self)
|
||||
self.register_custom_email_notification('TorrentFinishedEvent',
|
||||
self._on_torrent_finished_event)
|
||||
|
||||
def disable(self):
|
||||
self.deregister_custom_email_notification('TorrentFinishedEvent')
|
||||
CustomNotifications.disable(self)
|
||||
|
||||
def register_custom_email_notification(self, eventtype, handler):
|
||||
"""This is used to register email notifications for custom event types.
|
||||
|
||||
:param event: str, the event name
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return a tuple of (email_subject, email_contents).
|
||||
"""
|
||||
self._register_custom_provider('email', eventtype, handler)
|
||||
|
||||
def deregister_custom_email_notification(self, eventtype):
|
||||
self._deregister_custom_provider('email', eventtype)
|
||||
|
||||
def handle_custom_email_notification(self, result, eventtype):
|
||||
if not self.config['smtp_enabled']:
|
||||
return defer.succeed("SMTP notification not enabled.")
|
||||
subject, message = result
|
||||
log.debug("Spawning new thread to send email with subject: %s: %s",
|
||||
subject, message)
|
||||
# Spawn thread because we don't want Deluge to lock up while we send the
|
||||
# email.
|
||||
return threads.deferToThread(self._notify_email, subject, message)
|
||||
|
||||
def get_handled_events(self):
|
||||
handled_events = []
|
||||
for evt in sorted(known_events.keys()):
|
||||
if known_events[evt].__module__.startswith('deluge.event'):
|
||||
if evt not in ('TorrentFinishedEvent',):
|
||||
# Skip all un-handled built-in events
|
||||
continue
|
||||
classdoc = known_events[evt].__doc__.strip()
|
||||
handled_events.append((evt, classdoc))
|
||||
log.debug("Handled Notification Events: %s", handled_events)
|
||||
return handled_events
|
||||
|
||||
def _notify_email(self, subject='', message=''):
|
||||
log.debug("Email prepared")
|
||||
to_addrs = '; '.join(self.config['smtp_recipients'])
|
||||
headers = """\
|
||||
From: %(smtp_from)s
|
||||
To: %(smtp_recipients)s
|
||||
Subject: %(subject)s
|
||||
|
||||
|
||||
""" % {'smtp_from': self.config['smtp_from'],
|
||||
'subject': subject,
|
||||
'smtp_recipients': to_addrs}
|
||||
|
||||
message = '\r\n'.join((headers + message).splitlines())
|
||||
|
||||
try:
|
||||
try:
|
||||
# Python 2.6
|
||||
server = smtplib.SMTP(self.config["smtp_host"],
|
||||
self.config["smtp_port"],
|
||||
timeout=60)
|
||||
except:
|
||||
# Python 2.5
|
||||
server = smtplib.SMTP(self.config["smtp_host"],
|
||||
self.config["smtp_port"])
|
||||
except Exception, err:
|
||||
err_msg = _("There was an error sending the notification email:"
|
||||
" %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
|
||||
security_enabled = self.config['smtp_tls']
|
||||
|
||||
if security_enabled:
|
||||
server.ehlo()
|
||||
if not server.esmtp_features.has_key('starttls'):
|
||||
log.warning("TLS/SSL enabled but server does not support it")
|
||||
else:
|
||||
server.starttls()
|
||||
server.ehlo()
|
||||
|
||||
if self.config['smtp_user'] and self.config['smtp_pass']:
|
||||
try:
|
||||
server.login(self.config['smtp_user'], self.config['smtp_pass'])
|
||||
except smtplib.SMTPHeloError, err:
|
||||
err_msg = _("The server didn't reply properly to the helo "
|
||||
"greeting: %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
except smtplib.SMTPAuthenticationError, err:
|
||||
err_msg = _("The server didn't accept the username/password "
|
||||
"combination: %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
|
||||
try:
|
||||
try:
|
||||
server.sendmail(self.config['smtp_from'], to_addrs, message)
|
||||
except smtplib.SMTPException, err:
|
||||
err_msg = _("There was an error sending the notification email:"
|
||||
" %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
finally:
|
||||
if security_enabled:
|
||||
# avoid false failure detection when the server closes
|
||||
# the SMTP connection with TLS enabled
|
||||
import socket
|
||||
try:
|
||||
server.quit()
|
||||
except socket.sslerror:
|
||||
pass
|
||||
else:
|
||||
server.quit()
|
||||
return _("Notification email sent.")
|
||||
|
||||
|
||||
def _on_torrent_finished_event(self, torrent_id):
|
||||
log.debug("Handler for TorrentFinishedEvent called for CORE")
|
||||
torrent = component.get("TorrentManager")[torrent_id]
|
||||
torrent_status = torrent.get_status({})
|
||||
# Email
|
||||
subject = _("Finished Torrent \"%(name)s\"") % torrent_status
|
||||
message = _(
|
||||
"This email is to inform you that Deluge has finished "
|
||||
"downloading \"%(name)s\", which includes %(num_files)i files."
|
||||
"\nTo stop receiving these alerts, simply turn off email "
|
||||
"notification in Deluge's preferences.\n\n"
|
||||
"Thank you,\nDeluge."
|
||||
) % torrent_status
|
||||
return subject, message
|
||||
|
||||
d = defer.maybeDeferred(self.handle_custom_email_notification,
|
||||
[subject, message],
|
||||
"TorrentFinishedEvent")
|
||||
d.addCallback(self._on_notify_sucess, 'email')
|
||||
d.addErrback(self._on_notify_failure, 'email')
|
||||
return d
|
||||
|
||||
|
||||
class GtkUiNotifications(CustomNotifications):
|
||||
|
||||
def enable(self):
|
||||
CustomNotifications.enable(self)
|
||||
self.register_custom_blink_notification(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event_blink
|
||||
)
|
||||
self.register_custom_sound_notification(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event_sound
|
||||
)
|
||||
self.register_custom_popup_notification(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event_popup
|
||||
)
|
||||
|
||||
def disable(self):
|
||||
self.deregister_custom_blink_notification("TorrentFinishedEvent")
|
||||
self.deregister_custom_sound_notification("TorrentFinishedEvent")
|
||||
self.deregister_custom_popup_notification("TorrentFinishedEvent")
|
||||
CustomNotifications.disable(self)
|
||||
|
||||
def register_custom_popup_notification(self, eventtype, handler):
|
||||
"""This is used to register popup notifications for custom event types.
|
||||
|
||||
:param event: the event name
|
||||
:param type: string
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return a tuple of (popup_title, popup_contents).
|
||||
"""
|
||||
self._register_custom_provider('popup', eventtype, handler)
|
||||
|
||||
def deregister_custom_popup_notification(self, eventtype):
|
||||
self._deregister_custom_provider('popup', eventtype)
|
||||
|
||||
def register_custom_blink_notification(self, eventtype, handler):
|
||||
"""This is used to register blink notifications for custom event types.
|
||||
|
||||
:param event: str, the event name
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return `True` or `False` to blink or not the
|
||||
trayicon.
|
||||
"""
|
||||
self._register_custom_provider('blink', eventtype, handler)
|
||||
|
||||
def deregister_custom_blink_notification(self, eventtype):
|
||||
self._deregister_custom_provider('blink', eventtype)
|
||||
|
||||
def register_custom_sound_notification(self, eventtype, handler):
|
||||
"""This is used to register sound notifications for custom event types.
|
||||
|
||||
:param event: the event name
|
||||
:type event: string
|
||||
:param handler: function to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return either '' to use the sound defined on the
|
||||
notification preferences, the path to a sound file, which will then be
|
||||
played or None, where no sound will be played at all.
|
||||
"""
|
||||
self._register_custom_provider('sound', eventtype, handler)
|
||||
|
||||
def deregister_custom_sound_notification(self, eventtype):
|
||||
self._deregister_custom_provider('sound', eventtype)
|
||||
|
||||
def handle_custom_popup_notification(self, result, eventtype):
|
||||
title, message = result
|
||||
return defer.maybeDeferred(self.__popup, title, message)
|
||||
|
||||
def handle_custom_blink_notification(self, result, eventtype):
|
||||
if result:
|
||||
return defer.maybeDeferred(self.__blink)
|
||||
return defer.succeed("Won't blink. The returned value from the custom "
|
||||
"handler was: %s", result)
|
||||
|
||||
def handle_custom_sound_notification(self, result, eventtype):
|
||||
if isinstance(result, basestring):
|
||||
if not result and eventtype in self.config['custom_sounds']:
|
||||
return defer.maybeDeferred(
|
||||
self.__play_sound, self.config['custom_sounds'][eventtype])
|
||||
return defer.maybeDeferred(self.__play_sound, result)
|
||||
return defer.succeed("Won't play sound. The returned value from the "
|
||||
"custom handler was: %s", result)
|
||||
|
||||
def __blink(self):
|
||||
self.systray.blink(True)
|
||||
return defer.succeed(_("Notification Blink shown"))
|
||||
|
||||
def __popup(self, title='', message=''):
|
||||
import gtk
|
||||
if not self.config['popup_enabled']:
|
||||
return defer.succeed(_("Popup notification is not enabled."))
|
||||
if not POPUP_AVAILABLE:
|
||||
return defer.fail(_("pynotify is not installed"))
|
||||
|
||||
if pynotify.init("Deluge"):
|
||||
icon = gtk.gdk.pixbuf_new_from_file_at_size(
|
||||
deluge.common.get_pixmap("deluge.svg"), 48, 48)
|
||||
self.note = pynotify.Notification(title, message)
|
||||
self.note.set_icon_from_pixbuf(icon)
|
||||
if not self.note.show():
|
||||
err_msg = _("pynotify failed to show notification")
|
||||
log.warning(err_msg)
|
||||
return defer.fail(err_msg)
|
||||
return defer.succeed(_("Notification popup shown"))
|
||||
|
||||
def __play_sound(self, sound_path=''):
|
||||
if not self.config['sound_enabled']:
|
||||
return defer.succeed(_("Sound notification not enabled"))
|
||||
if not SOUND_AVAILABLE:
|
||||
err_msg = _("pygame is not installed")
|
||||
log.warning(err_msg)
|
||||
return defer.fail(err_msg)
|
||||
|
||||
pygame.init()
|
||||
try:
|
||||
if not sound_path:
|
||||
sound_path = self.config['sound_path']
|
||||
alert_sound = pygame.mixer.music
|
||||
alert_sound.load(sound_path)
|
||||
alert_sound.play()
|
||||
except pygame.error, message:
|
||||
err_msg = _("Sound notification failed %s") % (message)
|
||||
log.warning(err_msg)
|
||||
return defer.fail(err_msg)
|
||||
else:
|
||||
msg = _("Sound notification Success")
|
||||
log.info(msg)
|
||||
return defer.succeed(msg)
|
||||
|
||||
def _on_torrent_finished_event_blink(self, torrent_id):
|
||||
return True # Yes, Blink
|
||||
|
||||
def _on_torrent_finished_event_sound(self, torrent_id):
|
||||
# Since there's no custom sound hardcoded, just return ''
|
||||
return ''
|
||||
|
||||
def _on_torrent_finished_event_popup(self, torrent_id):
|
||||
d = client.core.get_torrent_status(torrent_id, ["name", "num_files"])
|
||||
d.addCallback(self._on_torrent_finished_event_got_torrent_status)
|
||||
d.addErrback(self._on_torrent_finished_event_torrent_status_failure)
|
||||
return d
|
||||
|
||||
def _on_torrent_finished_event_torrent_status_failure(self, failure):
|
||||
log.debug("Failed to get torrent status to be able to show the popup")
|
||||
|
||||
def _on_torrent_finished_event_got_torrent_status(self, torrent_status):
|
||||
log.debug("Handler for TorrentFinishedEvent GTKUI called. "
|
||||
"Got Torrent Status")
|
||||
title = _("Finished Torrent")
|
||||
message = _("The torrent \"%(name)s\" including %(num_files)i "
|
||||
"has finished downloading.") % torrent_status
|
||||
return title, message
|
||||
|
||||
|
||||
|
|
|
@ -37,12 +37,15 @@
|
|||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
|
||||
import smtplib
|
||||
from twisted.internet import defer, threads
|
||||
from deluge.event import known_events
|
||||
from deluge.log import LOG as log
|
||||
from deluge.plugins.pluginbase import CorePluginBase
|
||||
import deluge.configmanager
|
||||
from deluge.core.rpcserver import export
|
||||
|
||||
from notifications.common import CoreNotifications
|
||||
from notifications.common import CustomNotifications
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
"smtp_enabled": False,
|
||||
|
@ -59,6 +62,152 @@ DEFAULT_PREFS = {
|
|||
}
|
||||
}
|
||||
|
||||
class CoreNotifications(CustomNotifications):
|
||||
|
||||
def enable(self):
|
||||
CustomNotifications.enable(self)
|
||||
self.register_custom_email_notification('TorrentFinishedEvent',
|
||||
self._on_torrent_finished_event)
|
||||
|
||||
def disable(self):
|
||||
self.deregister_custom_email_notification('TorrentFinishedEvent')
|
||||
CustomNotifications.disable(self)
|
||||
|
||||
def register_custom_email_notification(self, eventtype, handler):
|
||||
"""This is used to register email notifications for custom event types.
|
||||
|
||||
:param event: str, the event name
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return a tuple of (email_subject, email_contents).
|
||||
"""
|
||||
self._register_custom_provider('email', eventtype, handler)
|
||||
|
||||
def deregister_custom_email_notification(self, eventtype):
|
||||
self._deregister_custom_provider('email', eventtype)
|
||||
|
||||
def handle_custom_email_notification(self, result, eventtype):
|
||||
if not self.config['smtp_enabled']:
|
||||
return defer.succeed("SMTP notification not enabled.")
|
||||
subject, message = result
|
||||
log.debug("Spawning new thread to send email with subject: %s: %s",
|
||||
subject, message)
|
||||
# Spawn thread because we don't want Deluge to lock up while we send the
|
||||
# email.
|
||||
return threads.deferToThread(self._notify_email, subject, message)
|
||||
|
||||
def get_handled_events(self):
|
||||
handled_events = []
|
||||
for evt in sorted(known_events.keys()):
|
||||
if known_events[evt].__module__.startswith('deluge.event'):
|
||||
if evt not in ('TorrentFinishedEvent',):
|
||||
# Skip all un-handled built-in events
|
||||
continue
|
||||
classdoc = known_events[evt].__doc__.strip()
|
||||
handled_events.append((evt, classdoc))
|
||||
log.debug("Handled Notification Events: %s", handled_events)
|
||||
return handled_events
|
||||
|
||||
def _notify_email(self, subject='', message=''):
|
||||
log.debug("Email prepared")
|
||||
to_addrs = '; '.join(self.config['smtp_recipients'])
|
||||
headers = """\
|
||||
From: %(smtp_from)s
|
||||
To: %(smtp_recipients)s
|
||||
Subject: %(subject)s
|
||||
|
||||
|
||||
""" % {'smtp_from': self.config['smtp_from'],
|
||||
'subject': subject,
|
||||
'smtp_recipients': to_addrs}
|
||||
|
||||
message = '\r\n'.join((headers + message).splitlines())
|
||||
|
||||
try:
|
||||
try:
|
||||
# Python 2.6
|
||||
server = smtplib.SMTP(self.config["smtp_host"],
|
||||
self.config["smtp_port"],
|
||||
timeout=60)
|
||||
except:
|
||||
# Python 2.5
|
||||
server = smtplib.SMTP(self.config["smtp_host"],
|
||||
self.config["smtp_port"])
|
||||
except Exception, err:
|
||||
err_msg = _("There was an error sending the notification email:"
|
||||
" %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
|
||||
security_enabled = self.config['smtp_tls']
|
||||
|
||||
if security_enabled:
|
||||
server.ehlo()
|
||||
if not server.esmtp_features.has_key('starttls'):
|
||||
log.warning("TLS/SSL enabled but server does not support it")
|
||||
else:
|
||||
server.starttls()
|
||||
server.ehlo()
|
||||
|
||||
if self.config['smtp_user'] and self.config['smtp_pass']:
|
||||
try:
|
||||
server.login(self.config['smtp_user'], self.config['smtp_pass'])
|
||||
except smtplib.SMTPHeloError, err:
|
||||
err_msg = _("The server didn't reply properly to the helo "
|
||||
"greeting: %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
except smtplib.SMTPAuthenticationError, err:
|
||||
err_msg = _("The server didn't accept the username/password "
|
||||
"combination: %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
|
||||
try:
|
||||
try:
|
||||
server.sendmail(self.config['smtp_from'], to_addrs, message)
|
||||
except smtplib.SMTPException, err:
|
||||
err_msg = _("There was an error sending the notification email:"
|
||||
" %s") % err
|
||||
log.error(err_msg)
|
||||
return err
|
||||
finally:
|
||||
if security_enabled:
|
||||
# avoid false failure detection when the server closes
|
||||
# the SMTP connection with TLS enabled
|
||||
import socket
|
||||
try:
|
||||
server.quit()
|
||||
except socket.sslerror:
|
||||
pass
|
||||
else:
|
||||
server.quit()
|
||||
return _("Notification email sent.")
|
||||
|
||||
|
||||
def _on_torrent_finished_event(self, torrent_id):
|
||||
log.debug("Handler for TorrentFinishedEvent called for CORE")
|
||||
torrent = component.get("TorrentManager")[torrent_id]
|
||||
torrent_status = torrent.get_status({})
|
||||
# Email
|
||||
subject = _("Finished Torrent \"%(name)s\"") % torrent_status
|
||||
message = _(
|
||||
"This email is to inform you that Deluge has finished "
|
||||
"downloading \"%(name)s\", which includes %(num_files)i files."
|
||||
"\nTo stop receiving these alerts, simply turn off email "
|
||||
"notification in Deluge's preferences.\n\n"
|
||||
"Thank you,\nDeluge."
|
||||
) % torrent_status
|
||||
return subject, message
|
||||
|
||||
d = defer.maybeDeferred(self.handle_custom_email_notification,
|
||||
[subject, message],
|
||||
"TorrentFinishedEvent")
|
||||
d.addCallback(self._on_notify_sucess, 'email')
|
||||
d.addErrback(self._on_notify_failure, 'email')
|
||||
return d
|
||||
|
||||
|
||||
class Core(CorePluginBase, CoreNotifications):
|
||||
def __init__(self, plugin_name):
|
||||
CorePluginBase.__init__(self, plugin_name)
|
||||
|
|
|
@ -49,8 +49,22 @@ import deluge.common
|
|||
import deluge.configmanager
|
||||
|
||||
# Relative imports
|
||||
from notifications.common import (get_resource, GtkUiNotifications,
|
||||
SOUND_AVAILABLE, POPUP_AVAILABLE)
|
||||
from common import get_resource, CustomNotifications
|
||||
|
||||
try:
|
||||
import pygame
|
||||
SOUND_AVAILABLE = True
|
||||
except ImportError:
|
||||
SOUND_AVAILABLE = False
|
||||
|
||||
try:
|
||||
import pynotify
|
||||
POPUP_AVAILABLE = True
|
||||
if deluge.common.windows_check():
|
||||
POPUP_AVAILABLE = False
|
||||
except ImportError:
|
||||
POPUP_AVAILABLE = False
|
||||
|
||||
|
||||
DEFAULT_PREFS = {
|
||||
# BLINK
|
||||
|
@ -76,6 +90,158 @@ RECIPIENT_FIELD, RECIPIENT_EDIT = range(2)
|
|||
SUB_NOT_SOUND) = range(6)
|
||||
SND_EVENT, SND_EVENT_DOC, SND_NAME, SND_PATH = range(4)
|
||||
|
||||
class GtkUiNotifications(CustomNotifications):
|
||||
|
||||
def enable(self):
|
||||
CustomNotifications.enable(self)
|
||||
self.register_custom_blink_notification(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event_blink
|
||||
)
|
||||
self.register_custom_sound_notification(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event_sound
|
||||
)
|
||||
self.register_custom_popup_notification(
|
||||
"TorrentFinishedEvent", self._on_torrent_finished_event_popup
|
||||
)
|
||||
|
||||
def disable(self):
|
||||
self.deregister_custom_blink_notification("TorrentFinishedEvent")
|
||||
self.deregister_custom_sound_notification("TorrentFinishedEvent")
|
||||
self.deregister_custom_popup_notification("TorrentFinishedEvent")
|
||||
CustomNotifications.disable(self)
|
||||
|
||||
def register_custom_popup_notification(self, eventtype, handler):
|
||||
"""This is used to register popup notifications for custom event types.
|
||||
|
||||
:param event: the event name
|
||||
:param type: string
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return a tuple of (popup_title, popup_contents).
|
||||
"""
|
||||
self._register_custom_provider('popup', eventtype, handler)
|
||||
|
||||
def deregister_custom_popup_notification(self, eventtype):
|
||||
self._deregister_custom_provider('popup', eventtype)
|
||||
|
||||
def register_custom_blink_notification(self, eventtype, handler):
|
||||
"""This is used to register blink notifications for custom event types.
|
||||
|
||||
:param event: str, the event name
|
||||
:param handler: function, to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return `True` or `False` to blink or not the
|
||||
trayicon.
|
||||
"""
|
||||
self._register_custom_provider('blink', eventtype, handler)
|
||||
|
||||
def deregister_custom_blink_notification(self, eventtype):
|
||||
self._deregister_custom_provider('blink', eventtype)
|
||||
|
||||
def register_custom_sound_notification(self, eventtype, handler):
|
||||
"""This is used to register sound notifications for custom event types.
|
||||
|
||||
:param event: the event name
|
||||
:type event: string
|
||||
:param handler: function to be called when `:param:event` is emitted
|
||||
|
||||
Your handler should return either '' to use the sound defined on the
|
||||
notification preferences, the path to a sound file, which will then be
|
||||
played or None, where no sound will be played at all.
|
||||
"""
|
||||
self._register_custom_provider('sound', eventtype, handler)
|
||||
|
||||
def deregister_custom_sound_notification(self, eventtype):
|
||||
self._deregister_custom_provider('sound', eventtype)
|
||||
|
||||
def handle_custom_popup_notification(self, result, eventtype):
|
||||
title, message = result
|
||||
return defer.maybeDeferred(self.__popup, title, message)
|
||||
|
||||
def handle_custom_blink_notification(self, result, eventtype):
|
||||
if result:
|
||||
return defer.maybeDeferred(self.__blink)
|
||||
return defer.succeed("Won't blink. The returned value from the custom "
|
||||
"handler was: %s", result)
|
||||
|
||||
def handle_custom_sound_notification(self, result, eventtype):
|
||||
if isinstance(result, basestring):
|
||||
if not result and eventtype in self.config['custom_sounds']:
|
||||
return defer.maybeDeferred(
|
||||
self.__play_sound, self.config['custom_sounds'][eventtype])
|
||||
return defer.maybeDeferred(self.__play_sound, result)
|
||||
return defer.succeed("Won't play sound. The returned value from the "
|
||||
"custom handler was: %s", result)
|
||||
|
||||
def __blink(self):
|
||||
self.systray.blink(True)
|
||||
return defer.succeed(_("Notification Blink shown"))
|
||||
|
||||
def __popup(self, title='', message=''):
|
||||
import gtk
|
||||
if not self.config['popup_enabled']:
|
||||
return defer.succeed(_("Popup notification is not enabled."))
|
||||
if not POPUP_AVAILABLE:
|
||||
return defer.fail(_("pynotify is not installed"))
|
||||
|
||||
if pynotify.init("Deluge"):
|
||||
icon = gtk.gdk.pixbuf_new_from_file_at_size(
|
||||
deluge.common.get_pixmap("deluge.svg"), 48, 48)
|
||||
self.note = pynotify.Notification(title, message)
|
||||
self.note.set_icon_from_pixbuf(icon)
|
||||
if not self.note.show():
|
||||
err_msg = _("pynotify failed to show notification")
|
||||
log.warning(err_msg)
|
||||
return defer.fail(err_msg)
|
||||
return defer.succeed(_("Notification popup shown"))
|
||||
|
||||
def __play_sound(self, sound_path=''):
|
||||
if not self.config['sound_enabled']:
|
||||
return defer.succeed(_("Sound notification not enabled"))
|
||||
if not SOUND_AVAILABLE:
|
||||
err_msg = _("pygame is not installed")
|
||||
log.warning(err_msg)
|
||||
return defer.fail(err_msg)
|
||||
|
||||
pygame.init()
|
||||
try:
|
||||
if not sound_path:
|
||||
sound_path = self.config['sound_path']
|
||||
alert_sound = pygame.mixer.music
|
||||
alert_sound.load(sound_path)
|
||||
alert_sound.play()
|
||||
except pygame.error, message:
|
||||
err_msg = _("Sound notification failed %s") % (message)
|
||||
log.warning(err_msg)
|
||||
return defer.fail(err_msg)
|
||||
else:
|
||||
msg = _("Sound notification Success")
|
||||
log.info(msg)
|
||||
return defer.succeed(msg)
|
||||
|
||||
def _on_torrent_finished_event_blink(self, torrent_id):
|
||||
return True # Yes, Blink
|
||||
|
||||
def _on_torrent_finished_event_sound(self, torrent_id):
|
||||
# Since there's no custom sound hardcoded, just return ''
|
||||
return ''
|
||||
|
||||
def _on_torrent_finished_event_popup(self, torrent_id):
|
||||
d = client.core.get_torrent_status(torrent_id, ["name", "num_files"])
|
||||
d.addCallback(self._on_torrent_finished_event_got_torrent_status)
|
||||
d.addErrback(self._on_torrent_finished_event_torrent_status_failure)
|
||||
return d
|
||||
|
||||
def _on_torrent_finished_event_torrent_status_failure(self, failure):
|
||||
log.debug("Failed to get torrent status to be able to show the popup")
|
||||
|
||||
def _on_torrent_finished_event_got_torrent_status(self, torrent_status):
|
||||
log.debug("Handler for TorrentFinishedEvent GTKUI called. "
|
||||
"Got Torrent Status")
|
||||
title = _("Finished Torrent")
|
||||
message = _("The torrent \"%(name)s\" including %(num_files)i "
|
||||
"has finished downloading.") % torrent_status
|
||||
return title, message
|
||||
|
||||
class GtkUI(GtkPluginBase, GtkUiNotifications):
|
||||
def __init__(self, plugin_name):
|
||||
|
|
|
@ -45,8 +45,12 @@ __author_email__ = "ufs@ufsoft.org"
|
|||
__version__ = "0.1"
|
||||
__url__ = "http://dev.deluge-torrent.org/"
|
||||
__license__ = "GPLv3"
|
||||
__description__ = ""
|
||||
__long_description__ = """"""
|
||||
__description__ = "Plugin which provides notifications to Deluge."
|
||||
__long_description__ = __description__ + """\
|
||||
Email, Popup, Blink and Sound notifications are supported.
|
||||
The plugin also allows other plugins to make use of itself for their own custom
|
||||
notifications.
|
||||
"""
|
||||
__pkg_data__ = {__plugin_name__.lower(): ["template/*", "data/*"]}
|
||||
|
||||
setup(
|
||||
|
|
Loading…
Reference in New Issue