blocking.py 4.22 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim.  If not, see <http://www.gnu.org/licenses/>.

# XEP-0191: Blocking Command

import nbxmpp
Philipp Hörist's avatar
Philipp Hörist committed
18
from nbxmpp.protocol import JID
Philipp Hörist's avatar
Philipp Hörist committed
19
from nbxmpp.namespaces import Namespace
Philipp Hörist's avatar
Philipp Hörist committed
20
from nbxmpp.structs import StanzaHandler
Philipp Hörist's avatar
Philipp Hörist committed
21
from nbxmpp.modules.util import raise_if_error
22
23

from gajim.common import app
Philipp Hörist's avatar
Philipp Hörist committed
24
from gajim.common.nec import NetworkEvent
Philipp Hörist's avatar
Philipp Hörist committed
25
from gajim.common.modules.base import BaseModule
Philipp Hörist's avatar
Philipp Hörist committed
26
from gajim.common.modules.util import as_task
27
28


Philipp Hörist's avatar
Philipp Hörist committed
29
class Blocking(BaseModule):
Philipp Hörist's avatar
Philipp Hörist committed
30

Philipp Hörist's avatar
Philipp Hörist committed
31
32
33
34
    _nbxmpp_extends = 'Blocking'
    _nbxmpp_methods = [
        'block',
        'unblock',
Philipp Hörist's avatar
Philipp Hörist committed
35
        'request_blocking_list',
Philipp Hörist's avatar
Philipp Hörist committed
36
    ]
Philipp Hörist's avatar
Philipp Hörist committed
37

38
    def __init__(self, con):
Philipp Hörist's avatar
Philipp Hörist committed
39
        BaseModule.__init__(self, con)
40
41
42
43

        self.blocked = []

        self.handlers = [
Philipp Hörist's avatar
Philipp Hörist committed
44
45
46
            StanzaHandler(name='iq',
                          callback=self._blocking_push_received,
                          typ='set',
Philipp Hörist's avatar
Philipp Hörist committed
47
                          ns=Namespace.BLOCKING),
48
49
        ]

Philipp Hörist's avatar
Philipp Hörist committed
50
        self.supported = False
Philipp Hörist's avatar
Philipp Hörist committed
51

52
    def pass_disco(self, info):
Philipp Hörist's avatar
Philipp Hörist committed
53
        if Namespace.BLOCKING not in info.features:
54
55
56
            return

        self.supported = True
Philipp Hörist's avatar
Philipp Hörist committed
57
58
59
        app.nec.push_incoming_event(
            NetworkEvent('feature-discovered',
                         account=self._account,
Philipp Hörist's avatar
Philipp Hörist committed
60
                         feature=Namespace.BLOCKING))
Philipp Hörist's avatar
Philipp Hörist committed
61

62
        self._log.info('Discovered blocking: %s', info.jid)
63

Philipp Hörist's avatar
Philipp Hörist committed
64
65
66
    @as_task
    def get_blocking_list(self):
        _task = yield
67

Philipp Hörist's avatar
Philipp Hörist committed
68
69
70
71
        blocking_list = yield self._nbxmpp('Blocking').request_blocking_list()

        raise_if_error(blocking_list)

72
        self.blocked = list(blocking_list)
Philipp Hörist's avatar
Philipp Hörist committed
73
74
75
76
77
78
79
80
81
82
83
84
        app.nec.push_incoming_event(NetworkEvent('blocking',
                                                 conn=self._con,
                                                 changed=self.blocked))
        yield blocking_list

    @as_task
    def update_blocking_list(self, block, unblock):
        _task = yield

        if block:
            result = yield self.block(block)
            raise_if_error(result)
85

Philipp Hörist's avatar
Philipp Hörist committed
86
87
88
89
90
91
92
93
94
        if unblock:
            result = yield self.unblock(unblock)
            raise_if_error(result)

        yield True

    def _blocking_push_received(self, _con, _stanza, properties):
        if not properties.is_blocking:
            return
95
96
97

        changed_list = []

Philipp Hörist's avatar
Philipp Hörist committed
98
99
100
        if properties.blocking.unblock_all:
            self.blocked = []
            for jid in self.blocked:
101
                self._presence_probe(jid)
Philipp Hörist's avatar
Philipp Hörist committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
            self._log.info('Unblock all Push')

        for jid in properties.blocking.unblock:
            changed_list.append(jid)
            if jid not in self.blocked:
                continue
            self.blocked.remove(jid)
            self._presence_probe(jid)
            self._log.info('Unblock Push: %s', jid)

        for jid in properties.blocking.block:
            if jid in self.blocked:
                continue
            changed_list.append(jid)
            self.blocked.append(jid)
            self._set_contact_offline(str(jid))
            self._log.info('Block Push: %s', jid)

        app.nec.push_incoming_event(NetworkEvent('blocking',
                                                 conn=self._con,
                                                 changed=changed_list))
123
124
125

        raise nbxmpp.NodeProcessed

Philipp Hörist's avatar
Philipp Hörist committed
126
    def _set_contact_offline(self, jid: str) -> None:
127
128
129
130
        contact_list = app.contacts.get_contacts(self._account, jid)
        for contact in contact_list:
            contact.show = 'offline'

Philipp Hörist's avatar
Philipp Hörist committed
131
    def _presence_probe(self, jid: JID) -> None:
Philipp Hörist's avatar
Philipp Hörist committed
132
        self._log.info('Presence probe: %s', jid)
133
134
        # Send a presence Probe to get the current Status
        probe = nbxmpp.Presence(jid, 'probe', frm=self._con.get_own_jid())
Philipp Hörist's avatar
Philipp Hörist committed
135
        self._nbxmpp().send(probe)
136
137
138
139


def get_instance(*args, **kwargs):
    return Blocking(*args, **kwargs), 'Blocking'