Modernize the Gmail plugin.
This commit is contained in:
parent
ea0381fa09
commit
27196a21ae
5 changed files with 209 additions and 150 deletions
|
@ -12,7 +12,7 @@ from sleekxmpp.plugins.base import register_plugin, load_plugin
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
# Non-standard
|
# Non-standard
|
||||||
'gmail_notify', # Gmail searching and notifications
|
'gmail', # Gmail searching and notifications
|
||||||
|
|
||||||
# XEPS
|
# XEPS
|
||||||
'xep_0004', # Data Forms
|
'xep_0004', # Data Forms
|
||||||
|
|
15
sleekxmpp/plugins/gmail/__init__.py
Normal file
15
sleekxmpp/plugins/gmail/__init__.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
"""
|
||||||
|
SleekXMPP: The Sleek XMPP Library
|
||||||
|
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
|
||||||
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
|
See the file LICENSE for copying permission.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sleekxmpp.plugins.base import register_plugin
|
||||||
|
|
||||||
|
from sleekxmpp.plugins.gmail import stanza
|
||||||
|
from sleekxmpp.plugins.gmail.notifications import Gmail
|
||||||
|
|
||||||
|
|
||||||
|
register_plugin(Gmail)
|
92
sleekxmpp/plugins/gmail/notifications.py
Normal file
92
sleekxmpp/plugins/gmail/notifications.py
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
"""
|
||||||
|
SleekXMPP: The Sleek XMPP Library
|
||||||
|
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
|
||||||
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
|
See the file LICENSE for copying permission.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from sleekxmpp.stanza import Iq
|
||||||
|
from sleekxmpp.xmlstream.handler import Callback
|
||||||
|
from sleekxmpp.xmlstream.matcher import MatchXPath
|
||||||
|
from sleekxmpp.xmlstream import register_stanza_plugin
|
||||||
|
from sleekxmpp.plugins import BasePlugin
|
||||||
|
from sleekxmpp.plugins.gmail import stanza
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Gmail(BasePlugin):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Google: Gmail Notifications
|
||||||
|
|
||||||
|
Also see <https://developers.google.com/talk/jep_extensions/gmail>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = 'gmail'
|
||||||
|
description = 'Google: Gmail Notifications'
|
||||||
|
dependencies = set()
|
||||||
|
stanza = stanza
|
||||||
|
|
||||||
|
def plugin_init(self):
|
||||||
|
register_stanza_plugin(Iq, stanza.GmailQuery)
|
||||||
|
register_stanza_plugin(Iq, stanza.MailBox)
|
||||||
|
register_stanza_plugin(Iq, stanza.NewMail)
|
||||||
|
|
||||||
|
self.xmpp.register_handler(
|
||||||
|
Callback('Gmail Result',
|
||||||
|
MatchXPath('{%s}iq/{%s}%s' % (
|
||||||
|
self.xmpp.default_ns,
|
||||||
|
stanza.MailBox.namespace,
|
||||||
|
stanza.MailBox.name)),
|
||||||
|
self._handle_gmail))
|
||||||
|
|
||||||
|
self.xmpp.register_handler(
|
||||||
|
Callback('Gmail New Mail',
|
||||||
|
MatchXPath('{%s}iq/{%s}%s' % (
|
||||||
|
self.xmpp.default_ns,
|
||||||
|
stanza.NewMail.namespace,
|
||||||
|
stanza.NewMail.name)),
|
||||||
|
self._handle_new_mail))
|
||||||
|
|
||||||
|
self._last_result_time = None
|
||||||
|
|
||||||
|
def plugin_end(self):
|
||||||
|
self.xmpp.remove_handler('Gmail Result')
|
||||||
|
self.xmpp.remove_handler('Gmail New Mail')
|
||||||
|
|
||||||
|
def _handle_gmail(self, iq):
|
||||||
|
mailbox = iq['gmail_results']
|
||||||
|
log.info('Gmail: Received%s %s emails',
|
||||||
|
' approximately' if mailbox['estimated'] else '',
|
||||||
|
mailbox['matched'])
|
||||||
|
self._last_result_time = mailbox['result_time']
|
||||||
|
self.xmpp.event('gmail_messages', iq)
|
||||||
|
|
||||||
|
def _handle_new_mail(self, iq):
|
||||||
|
log.info("Gmail: New emails received!")
|
||||||
|
self.xmpp.event('gmail_notify', iq)
|
||||||
|
self.check(block=False)
|
||||||
|
|
||||||
|
def check(self, block=True, timeout=None, callback=None):
|
||||||
|
return self.search(newer=self._last_result_time,
|
||||||
|
block=block,
|
||||||
|
timeout=timeout,
|
||||||
|
callback=callback)
|
||||||
|
|
||||||
|
def search(self, query=None, newer=None, block=True,
|
||||||
|
timeout=None, callback=None):
|
||||||
|
if not query:
|
||||||
|
log.info('Gmail: Checking for new email')
|
||||||
|
else:
|
||||||
|
log.info('Gmail: Searching for emails matching: "%s"', query)
|
||||||
|
iq = self.xmpp.Iq()
|
||||||
|
iq['type'] = 'get'
|
||||||
|
iq['to'] = self.xmpp.boundjid.bare
|
||||||
|
iq['gmail']['search'] = query
|
||||||
|
iq['gmail']['newer_than_time'] = newer
|
||||||
|
return iq.send(block=block, timeout=timeout, callback=callback)
|
101
sleekxmpp/plugins/gmail/stanza.py
Normal file
101
sleekxmpp/plugins/gmail/stanza.py
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
"""
|
||||||
|
SleekXMPP: The Sleek XMPP Library
|
||||||
|
Copyright (C) 2013 Nathanael C. Fritz, Lance J.T. Stout
|
||||||
|
This file is part of SleekXMPP.
|
||||||
|
|
||||||
|
See the file LICENSE for copying permission.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sleekxmpp.xmlstream import ElementBase, register_stanza_plugin
|
||||||
|
|
||||||
|
|
||||||
|
class GmailQuery(ElementBase):
|
||||||
|
namespace = 'google:mail:notify'
|
||||||
|
name = 'query'
|
||||||
|
plugin_attrib = 'gmail'
|
||||||
|
interfaces = set(['newer_than_time', 'newer_than_tid', 'search'])
|
||||||
|
|
||||||
|
def get_search(self):
|
||||||
|
return self._get_attr('q', '')
|
||||||
|
|
||||||
|
def set_search(self, search):
|
||||||
|
self._set_attr('q', search)
|
||||||
|
|
||||||
|
def del_search(self):
|
||||||
|
self._del_attr('q')
|
||||||
|
|
||||||
|
def get_newer_than_time(self):
|
||||||
|
return self._get_attr('newer-than-time', '')
|
||||||
|
|
||||||
|
def set_newer_than_time(self, value):
|
||||||
|
self._set_attr('newer-than-time', value)
|
||||||
|
|
||||||
|
def del_newer_than_time(self):
|
||||||
|
self._del_attr('newer-than-time')
|
||||||
|
|
||||||
|
def get_newer_than_tid(self):
|
||||||
|
return self._get_attr('newer-than-tid', '')
|
||||||
|
|
||||||
|
def set_newer_than_tid(self, value):
|
||||||
|
self._set_attr('newer-than-tid', value)
|
||||||
|
|
||||||
|
def del_newer_than_tid(self):
|
||||||
|
self._del_attr('newer-than-tid')
|
||||||
|
|
||||||
|
|
||||||
|
class MailBox(ElementBase):
|
||||||
|
namespace = 'google:mail:notify'
|
||||||
|
name = 'mailbox'
|
||||||
|
plugin_attrib = 'gmail_results'
|
||||||
|
interfaces = set(['result_time', 'url', 'matched', 'estimate'])
|
||||||
|
|
||||||
|
def get_matched(self):
|
||||||
|
return self._get_attr('total-matched', '')
|
||||||
|
|
||||||
|
def get_estimate(self):
|
||||||
|
return self._get_attr('total-estimate', '') == '1'
|
||||||
|
|
||||||
|
def get_result_time(self):
|
||||||
|
return self._get_attr('result-time', '')
|
||||||
|
|
||||||
|
|
||||||
|
class MailThread(ElementBase):
|
||||||
|
namespace = 'google:mail:notify'
|
||||||
|
name = 'mail-thread-info'
|
||||||
|
plugin_attrib = 'thread'
|
||||||
|
plugin_multi_attrib = 'threads'
|
||||||
|
interfaces = set(['tid', 'participation', 'messages', 'date',
|
||||||
|
'senders', 'url', 'labels', 'subject', 'snippet'])
|
||||||
|
sub_interfaces = set(['labels', 'subject', 'snippet'])
|
||||||
|
|
||||||
|
def get_senders(self):
|
||||||
|
result = []
|
||||||
|
senders = self.xml.findall('{%s}senders/{%s}sender' % (
|
||||||
|
self.namespace, self.namespace))
|
||||||
|
|
||||||
|
for sender in senders:
|
||||||
|
result.append(MailSender(xml=sender))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class MailSender(ElementBase):
|
||||||
|
namespace = 'google:mail:notify'
|
||||||
|
name = 'sender'
|
||||||
|
plugin_attrib = name
|
||||||
|
interfaces = set(['address', 'name', 'originator', 'unread'])
|
||||||
|
|
||||||
|
def get_originator(self):
|
||||||
|
return self.xml.attrib.get('originator', '0') == '1'
|
||||||
|
|
||||||
|
def get_unread(self):
|
||||||
|
return self.xml.attrib.get('unread', '0') == '1'
|
||||||
|
|
||||||
|
|
||||||
|
class NewMail(ElementBase):
|
||||||
|
namespace = 'google:mail:notify'
|
||||||
|
name = 'new-mail'
|
||||||
|
plugin_attrib = 'gmail_notification'
|
||||||
|
|
||||||
|
|
||||||
|
register_stanza_plugin(MailBox, MailThread, iterable=True)
|
|
@ -1,149 +0,0 @@
|
||||||
"""
|
|
||||||
SleekXMPP: The Sleek XMPP Library
|
|
||||||
Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
|
||||||
This file is part of SleekXMPP.
|
|
||||||
|
|
||||||
See the file LICENSE for copying permission.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
from . import base
|
|
||||||
from .. xmlstream.handler.callback import Callback
|
|
||||||
from .. xmlstream.matcher.xpath import MatchXPath
|
|
||||||
from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET, JID
|
|
||||||
from .. stanza.iq import Iq
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class GmailQuery(ElementBase):
|
|
||||||
namespace = 'google:mail:notify'
|
|
||||||
name = 'query'
|
|
||||||
plugin_attrib = 'gmail'
|
|
||||||
interfaces = set(('newer-than-time', 'newer-than-tid', 'q', 'search'))
|
|
||||||
|
|
||||||
def getSearch(self):
|
|
||||||
return self['q']
|
|
||||||
|
|
||||||
def setSearch(self, search):
|
|
||||||
self['q'] = search
|
|
||||||
|
|
||||||
def delSearch(self):
|
|
||||||
del self['q']
|
|
||||||
|
|
||||||
|
|
||||||
class MailBox(ElementBase):
|
|
||||||
namespace = 'google:mail:notify'
|
|
||||||
name = 'mailbox'
|
|
||||||
plugin_attrib = 'mailbox'
|
|
||||||
interfaces = set(('result-time', 'total-matched', 'total-estimate',
|
|
||||||
'url', 'threads', 'matched', 'estimate'))
|
|
||||||
|
|
||||||
def getThreads(self):
|
|
||||||
threads = []
|
|
||||||
for threadXML in self.xml.findall('{%s}%s' % (MailThread.namespace,
|
|
||||||
MailThread.name)):
|
|
||||||
threads.append(MailThread(xml=threadXML, parent=None))
|
|
||||||
return threads
|
|
||||||
|
|
||||||
def getMatched(self):
|
|
||||||
return self['total-matched']
|
|
||||||
|
|
||||||
def getEstimate(self):
|
|
||||||
return self['total-estimate'] == '1'
|
|
||||||
|
|
||||||
|
|
||||||
class MailThread(ElementBase):
|
|
||||||
namespace = 'google:mail:notify'
|
|
||||||
name = 'mail-thread-info'
|
|
||||||
plugin_attrib = 'thread'
|
|
||||||
interfaces = set(('tid', 'participation', 'messages', 'date',
|
|
||||||
'senders', 'url', 'labels', 'subject', 'snippet'))
|
|
||||||
sub_interfaces = set(('labels', 'subject', 'snippet'))
|
|
||||||
|
|
||||||
def getSenders(self):
|
|
||||||
senders = []
|
|
||||||
sendersXML = self.xml.find('{%s}senders' % self.namespace)
|
|
||||||
if sendersXML is not None:
|
|
||||||
for senderXML in sendersXML.findall('{%s}sender' % self.namespace):
|
|
||||||
senders.append(MailSender(xml=senderXML, parent=None))
|
|
||||||
return senders
|
|
||||||
|
|
||||||
|
|
||||||
class MailSender(ElementBase):
|
|
||||||
namespace = 'google:mail:notify'
|
|
||||||
name = 'sender'
|
|
||||||
plugin_attrib = 'sender'
|
|
||||||
interfaces = set(('address', 'name', 'originator', 'unread'))
|
|
||||||
|
|
||||||
def getOriginator(self):
|
|
||||||
return self.xml.attrib.get('originator', '0') == '1'
|
|
||||||
|
|
||||||
def getUnread(self):
|
|
||||||
return self.xml.attrib.get('unread', '0') == '1'
|
|
||||||
|
|
||||||
|
|
||||||
class NewMail(ElementBase):
|
|
||||||
namespace = 'google:mail:notify'
|
|
||||||
name = 'new-mail'
|
|
||||||
plugin_attrib = 'new-mail'
|
|
||||||
|
|
||||||
|
|
||||||
class gmail_notify(base.base_plugin):
|
|
||||||
"""
|
|
||||||
Google Talk: Gmail Notifications
|
|
||||||
"""
|
|
||||||
|
|
||||||
def plugin_init(self):
|
|
||||||
self.description = 'Google Talk: Gmail Notifications'
|
|
||||||
|
|
||||||
self.xmpp.registerHandler(
|
|
||||||
Callback('Gmail Result',
|
|
||||||
MatchXPath('{%s}iq/{%s}%s' % (self.xmpp.default_ns,
|
|
||||||
MailBox.namespace,
|
|
||||||
MailBox.name)),
|
|
||||||
self.handle_gmail))
|
|
||||||
|
|
||||||
self.xmpp.registerHandler(
|
|
||||||
Callback('Gmail New Mail',
|
|
||||||
MatchXPath('{%s}iq/{%s}%s' % (self.xmpp.default_ns,
|
|
||||||
NewMail.namespace,
|
|
||||||
NewMail.name)),
|
|
||||||
self.handle_new_mail))
|
|
||||||
|
|
||||||
registerStanzaPlugin(Iq, GmailQuery)
|
|
||||||
registerStanzaPlugin(Iq, MailBox)
|
|
||||||
registerStanzaPlugin(Iq, NewMail)
|
|
||||||
|
|
||||||
self.last_result_time = None
|
|
||||||
|
|
||||||
def handle_gmail(self, iq):
|
|
||||||
mailbox = iq['mailbox']
|
|
||||||
approx = ' approximately' if mailbox['estimated'] else ''
|
|
||||||
log.info('Gmail: Received%s %s emails', approx, mailbox['total-matched'])
|
|
||||||
self.last_result_time = mailbox['result-time']
|
|
||||||
self.xmpp.event('gmail_messages', iq)
|
|
||||||
|
|
||||||
def handle_new_mail(self, iq):
|
|
||||||
log.info("Gmail: New emails received!")
|
|
||||||
self.xmpp.event('gmail_notify')
|
|
||||||
self.checkEmail()
|
|
||||||
|
|
||||||
def getEmail(self, query=None):
|
|
||||||
return self.search(query)
|
|
||||||
|
|
||||||
def checkEmail(self):
|
|
||||||
return self.search(newer=self.last_result_time)
|
|
||||||
|
|
||||||
def search(self, query=None, newer=None):
|
|
||||||
if query is None:
|
|
||||||
log.info("Gmail: Checking for new emails")
|
|
||||||
else:
|
|
||||||
log.info('Gmail: Searching for emails matching: "%s"', query)
|
|
||||||
iq = self.xmpp.Iq()
|
|
||||||
iq['type'] = 'get'
|
|
||||||
iq['to'] = self.xmpp.boundjid.bare
|
|
||||||
iq['gmail']['q'] = query
|
|
||||||
iq['gmail']['newer-than-time'] = newer
|
|
||||||
return iq.send()
|
|
Loading…
Reference in a new issue