Ejemplo n.º 1
0
 def _get_preferred_format(self, sid, realm=None):
     if realm:
         name = 'xmpp_format_%s' % realm
     else:
         name = 'xmpp_format'
     SubscriptionSetting(self.env, name, self.xmpp_format_setting.default)
     return self.xmpp_format_setting.get_user_setting(sid)[0]
Ejemplo n.º 2
0
    def render_announcement_preference_box(self, req, panel):
        supported_realms = {}
        for producer in self.producers:
            for realm in producer.realms():
                for distributor in self.distributors:
                    for transport in distributor.transports():
                        for fmtr in self.formatters:
                            for style in fmtr.styles(transport, realm):
                                if realm not in supported_realms:
                                    supported_realms[realm] = set()
                                supported_realms[realm].add(style)

        settings = {}
        for realm in supported_realms:
            name = 'xmpp_format_%s' % realm
            settings[realm] = SubscriptionSetting(
                self.env, name,
                XmppDistributor(self.env).xmpp_format_setting.default)
        if req.method == "POST":
            for realm, setting in settings.items():
                name = 'xmpp_format_%s' % realm
                setting.set_user_setting(req.session,
                                         req.args.get(name),
                                         save=False)
            req.session.save()
        prefs = {}
        for realm, setting in settings.items():
            prefs[realm] = setting.get_user_setting(req.session.sid)[0]
        data = dict(
            realms=supported_realms,
            preferences=prefs,
        )
        return "prefs_announcer_xmpp.html", data
Ejemplo n.º 3
0
class SpecifiedXmppResolver(Component):
    implements(IAnnouncementAddressResolver, IAnnouncementPreferenceProvider)

    def __init__(self):
        self.setting = SubscriptionSetting(self.env, 'specified_xmpp')

    def get_address_for_name(self, name, authed):
        return self.setting.get_user_setting(name)[1]

    # IAnnouncementDistributor
    def get_announcement_preference_boxes(self, req):
        if req.authname != "anonymous":
            yield "xmppaddress", "Announcement XMPP Address"

    def render_announcement_preference_box(self, req, panel):
        if req.method == "POST":
            self.setting.set_user_setting(req.session,
                    req.args.get('specified_xmpp'))
        specified = self.setting.get_user_setting(req.session.sid)[1] or ''
        data = dict(specified_xmpp = specified,)
        return "prefs_announcer_xmppaddress.html", data
Ejemplo n.º 4
0
class SpecifiedXmppResolver(Component):
    implements(IAnnouncementAddressResolver, IAnnouncementPreferenceProvider)

    def __init__(self):
        self.setting = SubscriptionSetting(self.env, 'specified_xmpp')

    def get_address_for_name(self, name, authed):
        return self.setting.get_user_setting(name)[1]

    # IAnnouncementDistributor
    def get_announcement_preference_boxes(self, req):
        if req.authname != "anonymous":
            yield "xmppaddress", "Announcement XMPP Address"

    def render_announcement_preference_box(self, req, panel):
        if req.method == "POST":
            self.setting.set_user_setting(req.session,
                                          req.args.get('specified_xmpp'))
        specified = self.setting.get_user_setting(req.session.sid)[1] or ''
        data = dict(specified_xmpp=specified, )
        return "prefs_announcer_xmppaddress.html", data
Ejemplo n.º 5
0
class SpecifiedXmppResolver(Component):

    implements(IEmailAddressResolver, IAnnouncementPreferenceProvider)

    def __init__(self):
        self.setting = SubscriptionSetting(self.env, 'specified_xmpp')

    def get_address_for_session(self, sid, authed):
        return self.setting.get_user_setting(sid)[1]

    # IAnnouncementDistributor methods

    def get_announcement_preference_boxes(self, req):
        if req.authname != 'anonymous':
            yield 'xmppaddress', _("Announcement XMPP Address")

    def render_announcement_preference_box(self, req, panel):
        if req.method == 'POST':
            self.setting.set_user_setting(req.session,
                                          req.args.get('specified_xmpp'))
        specified = self.setting.get_user_setting(req.session.sid)[1] or ''
        data = dict(specified_xmpp=specified, )
        return 'prefs_announcer_xmppaddress.html', data
Ejemplo n.º 6
0
 def _settings(self):
     settings = {}
     for p in ('new_posts', 'all'):
         settings[p] = BoolSubscriptionSetting(self.env, 'fullblog_%s'%p)
     settings['my_posts'] = BoolSubscriptionSetting(
         self.env, 
         'fullblog_my_posts', 
         self.always_notify_author
     )
     settings['author_posts'] = SubscriptionSetting(
         self.env,
         'fullblog_author_posts'
     )
         
     return settings
Ejemplo n.º 7
0
 def __init__(self):
     self.setting = SubscriptionSetting(self.env, 'specified_xmpp')
Ejemplo n.º 8
0
 def _setting(self):
     return SubscriptionSetting(self.env, 'watch_users')
Ejemplo n.º 9
0
 def __init__(self):
     self.connections = {}
     self.delivery_queue = None
     self.xmpp_format_setting = SubscriptionSetting(self.env, 'xmpp_format',
                                                    self.default_format)
Ejemplo n.º 10
0
class XmppDistributor(Component):
    """Distribute announcements to XMPP clients."""

    implements(IAnnouncementDistributor)

    formatters = ExtensionPoint(IAnnouncementFormatter)

    resolvers = OrderedExtensionsOption(
        'announcer', 'xmpp_resolvers', IAnnouncementAddressResolver,
        'SpecifiedXmppResolver',
        """Comma seperated list of xmpp resolver components in the order
        they will be called.  If an xmpp address is resolved, the remaining
        resolvers will no be called.
        """)

    default_format = Option('announcer', 'default_xmpp_format', 'text/plain',
                            """Default format for xmpp messages.""")

    server = Option(
        'xmpp', 'server', None,
        """XMPP server hostname to use for jabber notifications.""")

    port = IntOption('xmpp', 'port', 5222,
                     """XMPP server port to use for jabber notification.""")

    user = Option('xmpp', 'user', 'trac@localhost',
                  """Sender address to use in xmpp message.""")

    resource = Option('xmpp', 'resource', 'TracAnnouncerPlugin',
                      """Sender resource to use in xmpp message.""")

    password = Option('xmpp', 'password', None,
                      """Password for XMPP server.""")

    use_threaded_delivery = BoolOption(
        'announcer', 'use_threaded_delivery', False,
        """If true, the actual delivery of the message will occur
            in a separate thread.  Enabling this will improve responsiveness
            for requests that end up with an announcement being sent over
            email. It requires building Python with threading support
            enabled-- which is usually the case. To test, start Python and
            type 'import threading' to see if it raises an error.
            """)

    def __init__(self):
        self.connections = {}
        self.delivery_queue = None
        self.xmpp_format_setting = SubscriptionSetting(self.env, 'xmpp_format',
                                                       self.default_format)

    def get_delivery_queue(self):
        if not self.delivery_queue:
            self.delivery_queue = Queue.Queue()
            thread = DeliveryThread(self.delivery_queue, self.send)
            thread.start()
        return self.delivery_queue

    # IAnnouncementDistributor
    def transports(self):
        yield "xmpp"

    def distribute(self, transport, recipients, event):
        self.log.info('XmppDistributor called')
        if transport != 'xmpp':
            return
        fmtdict = self._formats(transport, event.realm)
        if not fmtdict:
            self.log.error("XmppDistributor No formats found for %s %s" %
                           (transport, event.realm))
            return
        msgdict = {}
        for name, authed, addr in recipients:
            fmt = name and \
                self._get_preferred_format(name, event.realm)
            if fmt not in fmtdict:
                self.log.debug(("XmppDistributor format %s not available " +
                                "for %s %s, looking for an alternative") %
                               (fmt, transport, event.realm))
                # If the fmt is not available for this realm, then try to find
                # an alternative
                oldfmt = fmt
                fmt = None
                for f in fmtdict.values():
                    fmt = f.alternative_style_for(transport, event.realm,
                                                  oldfmt)
                    if fmt: break
            if not fmt:
                self.log.error(
                    "XmppDistributor was unable to find a formatter " +
                    "for format %s" % k)
                continue
            # TODO:  This won't work with multiple distributors
            #rslvr = None
            # figure out what the addr should be if it's not defined
            #for rslvr in self.resolvers:
            #    addr = rslvr.get_address_for_name(name, authed)
            #    if addr: break
            rslvr = SpecifiedXmppResolver(self.env)
            addr = rslvr.get_address_for_name(name, authed)
            if addr:
                self.log.debug("XmppDistributor found the " \
                        "address '%s' for '%s (%s)' via: %s"%(
                        addr, name, authed and \
                        'authenticated' or 'not authenticated',
                        rslvr.__class__.__name__))
                # ok, we found an addr, add the message
                msgdict.setdefault(fmt, set()).add((name, authed, addr))
            else:
                self.log.debug("XmppDistributor was unable to find an " \
                        "address for: %s (%s)"%(name, authed and \
                        'authenticated' or 'not authenticated'))
        for k, v in msgdict.items():
            if not v or not fmtdict.get(k):
                continue
            self.log.debug("XmppDistributor is sending event as '%s' to: %s" %
                           (fmt, ', '.join(x[2] for x in v)))
            self._do_send(transport, event, k, v, fmtdict[k])

    def _formats(self, transport, realm):
        "Find valid formats for transport and realm"
        formats = {}
        for f in self.formatters:
            for style in f.styles(transport, realm):
                formats[style] = f
        self.log.debug(
            "XmppDistributor has found the following formats capable "
            "of handling '%s' of '%s': %s" %
            (transport, realm, ', '.join(formats.keys())))
        if not formats:
            self.log.error("XmppDistributor is unable to continue " \
                    "without supporting formatters.")
        return formats

    def _get_preferred_format(self, sid, realm=None):
        if realm:
            name = 'xmpp_format_%s' % realm
        else:
            name = 'xmpp_format'
        setting = SubscriptionSetting(self.env, name,
                                      self.xmpp_format_setting.default)
        return self.xmpp_format_setting.get_user_setting(sid)[0]

    def _do_send(self, transport, event, format, recipients, formatter):
        message = formatter.format(transport, event.realm, format, event)

        package = (recipients, message)

        start = time.time()
        if self.use_threaded_delivery:
            self.get_delivery_queue().put(package)
        else:
            self.send(*package)
        stop = time.time()
        self.log.debug("XmppDistributor took %s seconds to send."\
                %(round(stop-start,2)))

    def send(self, recipients, message):
        """Send message to recipients via xmpp."""
        jid = JID(self.user)
        if self.server:
            server = self.server
        else:
            server = jid.getDomain()
        cl = Client(server, port=self.port, debug=[])
        if not cl.connect():
            raise IOError("Couldn't connect to xmpp server %s" % server)
        if not cl.auth(jid.getNode(), self.password, resource=self.resource):
            cl.Connection.disconnect()
            raise IOError("Xmpp auth erro using %s to %s" % (jid, server))
        default_domain = jid.getDomain()
        for recip in recipients:
            cl.send(Message(recip[2], message))
Ejemplo n.º 11
0
 def __init__(self):
     self.connections = {}
     self.delivery_queue = None
     self.xmpp_format_setting = \
         SubscriptionSetting(self.env, 'xmpp_format', self.default_format)
Ejemplo n.º 12
0
class XmppDistributor(Component):
    """Distribute announcements to XMPP clients."""

    implements(IAnnouncementDistributor)

    formatters = ExtensionPoint(IAnnouncementFormatter)

    resolvers = OrderedExtensionsOption('announcer', 'xmpp_resolvers',
        IEmailAddressResolver, 'SpecifiedXmppResolver',
        """Comma seperated list of xmpp resolver components in the order
        they will be called.  If an xmpp address is resolved, the remaining
        resolvers will no be called.
        """)

    default_format = Option('announcer', 'default_xmpp_format',
        'text/plain', """Default format for xmpp messages.""")

    server = Option('xmpp', 'server', None,
        """XMPP server hostname to use for jabber notifications.""")

    port = IntOption('xmpp', 'port', 5222,
        """XMPP server port to use for jabber notification.""")

    user = Option('xmpp', 'user', 'trac@localhost',
        """Sender address to use in xmpp message.""")

    resource = Option('xmpp', 'resource', 'TracAnnouncerPlugin',
        """Sender resource to use in xmpp message.""")

    password = Option('xmpp', 'password', None,
        """Password for XMPP server.""")

    use_threaded_delivery = BoolOption('announcer', 'use_threaded_delivery',
        False,
        """If true, the actual delivery of the message will occur
        in a separate thread.  Enabling this will improve responsiveness
        for requests that end up with an announcement being sent over
        email. It requires building Python with threading support
        enabled-- which is usually the case. To test, start Python and
        type 'import threading' to see if it raises an error.
        """)

    def __init__(self):
        self.connections = {}
        self.delivery_queue = None
        self.xmpp_format_setting = \
            SubscriptionSetting(self.env, 'xmpp_format', self.default_format)

    def get_delivery_queue(self):
        if not self.delivery_queue:
            self.delivery_queue = Queue.Queue()
            thread = DeliveryThread(self.delivery_queue, self.send)
            thread.start()
        return self.delivery_queue

    # IAnnouncementDistributor methods

    def transports(self):
        yield 'xmpp'

    def distribute(self, transport, recipients, event):
        self.log.info("XmppDistributor called")
        if transport != 'xmpp':
            return
        fmtdict = self._formats(transport, event.realm)
        if not fmtdict:
            self.log.error("XmppDistributor No formats found for %s %s",
                           transport, event.realm)
            return
        msgdict = {}
        for name, authed, address in recipients:
            fmt = name and self._get_preferred_format(name, event.realm)
            old_fmt = fmt
            if fmt not in fmtdict:
                self.log.debug("XmppDistributor format %s not available "
                               "for %s %s, looking for an alternative",
                               fmt, transport, event.realm)
                # If the fmt is not available for this realm, then try to find
                # an alternative
                fmt = None
                for f in fmtdict.values():
                    fmt = f.alternative_style_for(
                        transport, event.realm, old_fmt)
                    if fmt:
                        break
            if not fmt:
                self.log.error("XmppDistributor was unable to find a "
                               "formatter for format %s", old_fmt)
                continue
            # TODO:  This won't work with multiple distributors
            # rslvr = None
            # figure out what the addr should be if it's not defined
            # for rslvr in self.resolvers:
            #    addr = rslvr.get_address_for_name(name, authed)
            #    if addr: break
            resolver = SpecifiedXmppResolver(self.env)
            address = resolver.get_address_for_session(name, authed)
            if address:
                self.log.debug("XmppDistributor found the address '%s' for "
                               "'%s (%s)' via: %s", address, name, authed and
                               'authenticated' or 'not authenticated',
                               resolver.__class__.__name__)
                # ok, we found an addr, add the message
                msgdict.setdefault(fmt, set()).add((name, authed, address))
            else:
                self.log.debug("XmppDistributor was unable to find an "
                               "address for: %s (%s)", name, authed and
                               'authenticated' or 'not authenticated')
        for k, v in msgdict.items():
            fmt = fmtdict.get(k)
            if not v or not fmt:
                continue
            self.log.debug("XmppDistributor is sending event as '%s' to: %s",
                           fmt, ', '.join(x[2] for x in v))
            self._do_send(transport, event, k, v, fmt)

    def _formats(self, transport, realm):
        """Find valid formats for transport and realm."""
        formats = {}
        for f in self.formatters:
            for style in f.styles(transport, realm):
                formats[style] = f
        self.log.debug("XmppDistributor has found the following formats "
                       "capable of handling '%s' of '%s': %s", transport,
                       realm, ', '.join(formats.keys()))
        if not formats:
            self.log.error("XmppDistributor is unable to continue without "
                           "supporting formatters.")
        return formats

    def _get_preferred_format(self, sid, realm=None):
        if realm:
            name = 'xmpp_format_%s' % realm
        else:
            name = 'xmpp_format'
        SubscriptionSetting(self.env, name, self.xmpp_format_setting.default)
        return self.xmpp_format_setting.get_user_setting(sid)[0]

    def _do_send(self, transport, event, format, recipients, formatter):
        message = formatter.format(transport, event.realm, format, event)

        package = (recipients, message)

        start = time.time()
        if self.use_threaded_delivery:
            self.get_delivery_queue().put(package)
        else:
            self.send(*package)
        stop = time.time()
        self.log.debug("XmppDistributor took %s seconds to send.",
                       round(stop - start, 2))

    def send(self, recipients, message):
        """Send message to recipients via xmpp."""
        jid = JID(self.user)
        if self.server:
            server = self.server
        else:
            server = jid.getDomain()
        cl = Client(server, port=self.port, debug=[])
        if not cl.connect():
            raise IOError("Couldn't connect to xmpp server %s" % server)
        if not cl.auth(jid.getNode(), self.password, resource=self.resource):
            cl.Connection.disconnect()
            raise IOError("Xmpp auth erro using %s to %s", jid, server)
        for recip in recipients:
            cl.send(Message(recip[2], message))
Ejemplo n.º 13
0
 def __init__(self):
     self.setting = SubscriptionSetting(self.env, 'specified_xmpp')
Ejemplo n.º 14
0
 def _setting(self):
     return SubscriptionSetting(self.env, 'wiki_pattern')