summaryrefslogtreecommitdiff
path: root/sleekxmpp/plugins/xep_0153/vcard_avatar.py
blob: 3f36d13590bfcc97c4cc7886543912fcf7de8b1f (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
"""
    SleekXMPP: The Sleek XMPP Library
    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
    This file is part of SleekXMPP.

    See the file LICENSE for copying permission.
"""

import hashlib
import logging

from sleekxmpp.stanza import Presence
from sleekxmpp.xmlstream import register_stanza_plugin
from sleekxmpp.xmlstream.matcher import StanzaPath
from sleekxmpp.xmlstream.handler import Callback
from sleekxmpp.plugins.base import BasePlugin
from sleekxmpp.plugins.xep_0153 import stanza, VCardTempUpdate


log = logging.getLogger(__name__)


class XEP_0153(BasePlugin):

    name = 'xep_0153'
    description = 'XEP-0153: vCard-Based Avatars'
    dependencies = set(['xep_0054'])
    stanza = stanza

    def plugin_init(self):
        self._hashes = {}

        register_stanza_plugin(Presence, VCardTempUpdate)

        self.xmpp.add_filter('out', self._update_presence)

        self.xmpp.add_event_handler('session_start', self._start)

        self.xmpp.add_event_handler('presence_available', self._recv_presence)
        self.xmpp.add_event_handler('presence_dnd', self._recv_presence)
        self.xmpp.add_event_handler('presence_xa', self._recv_presence)
        self.xmpp.add_event_handler('presence_chat', self._recv_presence)
        self.xmpp.add_event_handler('presence_away', self._recv_presence)

        self.api.register(self._set_hash, 'set_hash', default=True)
        self.api.register(self._get_hash, 'get_hash', default=True)

    def set_avatar(self, jid=None, avatar=None, mtype=None, block=True,
                   timeout=None, callback=None):
        vcard = self.xmpp['xep_0054'].get_vcard(jid, cached=True)
        vcard = vcard['vcard_temp']
        vcard['PHOTO']['TYPE'] = mtype
        vcard['PHOTO']['BINVAL'] = avatar
        self.xmpp['xep_0054'].publish_vcard(jid=jid, vcard=vcard)
        self._reset_hash(jid)

    def _start(self, event):
        self.xmpp['xep_0054'].get_vcard()

    def _update_presence(self, stanza):
        if not isinstance(stanza, Presence):
            return stanza

        current_hash = self.api['get_hash'](stanza['from'])
        stanza['vcard_temp_update']['photo'] = current_hash
        return stanza

    def _reset_hash(self, jid=None):
        own_jid = (jid.bare == self.xmpp.boundjid.bare)
        if self.xmpp.is_component:
            own_jid = (jid.domain == self.xmpp.boundjid.domain)

        if jid is not None:
            jid = jid.bare
        self.api['set_hash'](jid, args=None)
        if own_jid:
            self.xmpp.roster[jid].send_last_presence()

        iq = self.xmpp['xep_0054'].get_vcard(
                jid=jid,
                ifrom=self.xmpp.boundjid)
        data = iq['vcard_temp']['PHOTO']['BINVAL']
        if not data:
            new_hash = ''
        else:
            new_hash = hashlib.sha1(data).hexdigest()
        self.api['set_hash'](jid, args=new_hash)
        if own_jid:
            self.xmpp.roster[jid].send_last_presence()

    def _recv_presence(self, pres):
        if not pres.match('presence/vcard_temp_update'):
            self.api['set_hash'](pres['from'], args=None)
            return
        data = pres['vcard_temp_update']['photo']
        if data is None:
            return
        elif data == '' or data != self.api['get_hash'](pres['to']):
            self._reset_hash(pres['from'])

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

    def _get_hash(self, jid, node, ifrom, args):
        return self._hashes.get(jid.bare, None)

    def _set_hash(self, jid, node, ifrom, args):
        self._hashes[jid.bare] = args