vcard_temp.py 5.03 KB
Newer Older
Lance Stout's avatar
Lance Stout committed
1

2 3 4 5
# Slixmpp: The Slick XMPP Library
# Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
# This file is part of Slixmpp.
# See the file LICENSE for copying permission.
Lance Stout's avatar
Lance Stout committed
6
import logging
7
from typing import Optional
Lance Stout's avatar
Lance Stout committed
8

9 10
from slixmpp import JID
from slixmpp.stanza import Iq
louiz’'s avatar
louiz’ committed
11 12
from slixmpp.exceptions import XMPPError
from slixmpp.xmlstream import register_stanza_plugin
mathieui's avatar
mathieui committed
13
from slixmpp.xmlstream.handler import CoroutineCallback
louiz’'s avatar
louiz’ committed
14 15 16
from slixmpp.xmlstream.matcher import StanzaPath
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0054 import VCardTemp, stanza
Lance Stout's avatar
Lance Stout committed
17 18 19 20 21 22 23 24 25 26 27 28 29


log = logging.getLogger(__name__)


class XEP_0054(BasePlugin):

    """
    XEP-0054: vcard-temp
    """

    name = 'xep_0054'
    description = 'XEP-0054: vcard-temp'
30
    dependencies = {'xep_0030', 'xep_0082'}
Lance Stout's avatar
Lance Stout committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    stanza = stanza

    def plugin_init(self):
        """
        Start the XEP-0054 plugin.
        """
        register_stanza_plugin(Iq, VCardTemp)


        self.api.register(self._set_vcard, 'set_vcard', default=True)
        self.api.register(self._get_vcard, 'get_vcard', default=True)
        self.api.register(self._del_vcard, 'del_vcard', default=True)

        self._vcard_cache = {}

        self.xmpp.register_handler(
mathieui's avatar
mathieui committed
47
                CoroutineCallback('VCardTemp',
Lance Stout's avatar
Lance Stout committed
48 49 50
                    StanzaPath('iq/vcard_temp'),
                    self._handle_get_vcard))

51 52 53 54 55 56 57
    def plugin_end(self):
        self.xmpp.remove_handler('VCardTemp')
        self.xmpp['xep_0030'].del_feature(feature='vcard-temp')

    def session_bind(self, jid):
        self.xmpp['xep_0030'].add_feature('vcard-temp')

58 59
    def make_vcard(self) -> VCardTemp:
        """Return an empty vcard element."""
Lance Stout's avatar
Lance Stout committed
60 61
        return VCardTemp()

mathieui's avatar
mathieui committed
62 63 64 65
    async def get_vcard(self, jid: Optional[JID] = None, *,
                        local: Optional[bool] = None, cached: bool = False,
                        ifrom: Optional[JID] = None,
                        **iqkwargs) -> Iq:
66 67
        """Retrieve a VCard.

mathieui's avatar
mathieui committed
68 69 70
        .. versionchanged:: 1.8.0
            This function is now a coroutine.

71 72 73 74 75
        :param jid: JID of the entity to fetch the VCard from.
        :param local: Only check internally for a vcard.
        :param cached: Whether to check in the local cache before
                       sending a query.
        """
76 77 78 79 80 81 82 83 84 85 86 87
        if local is None:
            if jid is not None and not isinstance(jid, JID):
                jid = JID(jid)
                if self.xmpp.is_component:
                    if jid.domain == self.xmpp.boundjid.domain:
                        local = True
                else:
                    if str(jid) == str(self.xmpp.boundjid):
                        local = True
                jid = jid.full
            elif jid in (None, ''):
                local = True
Lance Stout's avatar
Lance Stout committed
88

89
        if local:
mathieui's avatar
mathieui committed
90
            vcard = await self.api['get_vcard'](jid, None, ifrom)
Lance Stout's avatar
Lance Stout committed
91 92
            if not isinstance(vcard, Iq):
                iq = self.xmpp.Iq()
93 94
                if vcard is None:
                    vcard = VCardTemp()
Lance Stout's avatar
Lance Stout committed
95 96 97 98
                iq.append(vcard)
                return iq
            return vcard

99
        if cached:
mathieui's avatar
mathieui committed
100
            vcard = await self.api['get_vcard'](jid, None, ifrom)
101 102 103 104 105 106 107
            if vcard is not None:
                if not isinstance(vcard, Iq):
                    iq = self.xmpp.Iq()
                    iq.append(vcard)
                    return iq
                return vcard

108
        iq = self.xmpp.make_iq_get(ito=jid, ifrom=ifrom)
Lance Stout's avatar
Lance Stout committed
109
        iq.enable('vcard_temp')
mathieui's avatar
mathieui committed
110
        return await iq.send(**iqkwargs)
Lance Stout's avatar
Lance Stout committed
111

mathieui's avatar
mathieui committed
112 113 114
    async def publish_vcard(self, vcard: Optional[VCardTemp] = None,
                            jid: Optional[JID] = None,
                            ifrom: Optional[JID] = None, **iqkwargs):
115 116
        """Publish a vcard.

mathieui's avatar
mathieui committed
117 118 119
        .. versionchanged:: 1.8.0
            This function is now a coroutine.

120 121 122
        :param vcard: The VCard to publish.
        :param jid: The JID to publish the VCard to.
        """
mathieui's avatar
mathieui committed
123
        await self.api['set_vcard'](jid, None, ifrom, vcard)
Lance Stout's avatar
Lance Stout committed
124 125 126
        if self.xmpp.is_component:
            return

127
        iq = self.xmpp.make_iq_set(ito=jid, ifrom=ifrom)
Lance Stout's avatar
Lance Stout committed
128
        iq.append(vcard)
mathieui's avatar
mathieui committed
129
        await iq.send(**iqkwargs)
Lance Stout's avatar
Lance Stout committed
130

mathieui's avatar
mathieui committed
131
    async def _handle_get_vcard(self, iq: Iq):
Lance Stout's avatar
Lance Stout committed
132
        if iq['type'] == 'result':
mathieui's avatar
mathieui committed
133
            await self.api['set_vcard'](jid=iq['from'], args=iq['vcard_temp'])
Lance Stout's avatar
Lance Stout committed
134
            return
135
        elif iq['type'] == 'get' and self.xmpp.is_component:
mathieui's avatar
mathieui committed
136
            vcard = await self.api['get_vcard'](iq['to'].bare, ifrom=iq['from'])
Lance Stout's avatar
Lance Stout committed
137 138 139
            if isinstance(vcard, Iq):
                vcard.send()
            else:
mathieui's avatar
mathieui committed
140
                iq = iq.reply()
Lance Stout's avatar
Lance Stout committed
141 142
                iq.append(vcard)
                iq.send()
143
        elif iq['type'] == 'set':
Lance Stout's avatar
Lance Stout committed
144 145 146 147 148 149 150 151
            raise XMPPError('service-unavailable')

    # =================================================================

    def _set_vcard(self, jid, node, ifrom, vcard):
        self._vcard_cache[jid.bare] = vcard

    def _get_vcard(self, jid, node, ifrom, vcard):
152
        return self._vcard_cache.get(jid.bare, None)
Lance Stout's avatar
Lance Stout committed
153 154 155 156

    def _del_vcard(self, jid, node, ifrom, vcard):
        if jid.bare in self._vcard_cache:
            del self._vcard_cache[jid.bare]