summaryrefslogtreecommitdiff
path: root/slixmpp/plugins/xep_0030/stanza/items.py
blob: 0e23849273f9882c5be62df5fec1f8e55768afec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""
    Slixmpp: The Slick XMPP Library
    Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
    This file is part of Slixmpp.

    See the file LICENSE for copying permission.
"""

from slixmpp.xmlstream import ElementBase, register_stanza_plugin


class DiscoItems(ElementBase):

    """
    Example disco#items stanzas:
        <iq type="get">
          <query xmlns="http://jabber.org/protocol/disco#items" />
        </iq>

        <iq type="result">
          <query xmlns="http://jabber.org/protocol/disco#items">
            <item jid="chat.example.com"
                  node="xmppdev"
                  name="XMPP Dev" />
            <item jid="chat.example.com"
                  node="slixdev"
                  name="Slixmpp Dev" />
          </query>
        </iq>

    Stanza Interface:
        node  -- The name of the node to either
                 query or return info from.
        items -- A list of 3-tuples, where each tuple contains
                 the JID, node, and name of an item.

    Methods:
        add_item  -- Add a single new item.
        del_item  -- Remove a single item.
        get_items -- Return all items.
        set_items -- Set or replace all items.
        del_items -- Remove all items.
    """

    name = 'query'
    namespace = 'http://jabber.org/protocol/disco#items'
    plugin_attrib = 'disco_items'
    interfaces = set(('node', 'items'))

    # Cache items
    _items = set()

    def setup(self, xml=None):
        """
        Populate the stanza object using an optional XML object.

        Overrides ElementBase.setup

        Caches item information.

        Arguments:
            xml -- Use an existing XML object for the stanza's values.
        """
        ElementBase.setup(self, xml)
        self._items = set([item[0:2] for item in self['items']])

    def add_item(self, jid, node=None, name=None):
        """
        Add a new item element. Each item is required to have a
        JID, but may also specify a node value to reference
        non-addressable entitities.

        Arguments:
            jid  -- The JID for the item.
            node -- Optional additional information to reference
                    non-addressable items.
            name -- Optional human readable name for the item.
        """
        if (jid, node) not in self._items:
            self._items.add((jid, node))
            item = DiscoItem(parent=self)
            item['jid'] = jid
            item['node'] = node
            item['name'] = name
            self.iterables.append(item)
            return True
        return False

    def del_item(self, jid, node=None):
        """
        Remove a single item.

        Arguments:
            jid  -- JID of the item to remove.
            node -- Optional extra identifying information.
        """
        if (jid, node) in self._items:
            for item_xml in self.findall('{%s}item' % self.namespace):
                item = (item_xml.attrib['jid'],
                        item_xml.attrib.get('node', None))
                if item == (jid, node):
                    self.xml.remove(item_xml)
                    return True
        return False

    def get_items(self):
        """Return all items."""
        items = set()
        for item in self['substanzas']:
            if isinstance(item, DiscoItem):
                items.add((item['jid'], item['node'], item['name']))
        return items

    def set_items(self, items):
        """
        Set or replace all items. The given items must be in a
        list or set where each item is a tuple of the form:
            (jid, node, name)

        Arguments:
            items -- A series of items in tuple format.
        """
        self.del_items()
        for item in items:
            jid, node, name = item
            self.add_item(jid, node, name)

    def del_items(self):
        """Remove all items."""
        self._items = set()
        items = [i for i in self.iterables if isinstance(i, DiscoItem)]
        for item in items:
            self.xml.remove(item.xml)
            self.iterables.remove(item)


class DiscoItem(ElementBase):
    name = 'item'
    namespace = 'http://jabber.org/protocol/disco#items'
    plugin_attrib = name
    interfaces = set(('jid', 'node', 'name'))

    def get_node(self):
        """Return the item's node name or ``None``."""
        return self._get_attr('node', None)

    def get_name(self):
        """Return the item's human readable name, or ``None``."""
        return self._get_attr('name', None)


register_stanza_plugin(DiscoItems, DiscoItem, iterable=True)