annotate sat_frontends/jp/cmd_roster.py @ 3237:b0c57c9a4bd8

plugin XEP-0384: OMEMO trust policy: OMEMO trust policy can now be specified. For now there are 2 policies: - `manual`: each new device fingerprint must be explicitly trusted or not before the device can be used, and the message sent - `BTBV` (Blind Trust Before Verification): each new device fingerprint is automically trusted, until user manually trust or not a device, in which case the behaviour becomes the same as for `manual` for the entity. When using the Trust UI, user can put the entity back to blind trust if they wish. A message is send as feedback to user when a new device is/must be trusted, trying to explain clearly what's happening to the user. Devices which have been automically trusted are marked, so user can know which ones may cause security issue.
author Goffi <goffi@goffi.org>
date Fri, 27 Mar 2020 10:02:14 +0100
parents 559a625a236b
children 012e89fb2dd1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3137
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
1 #!/usr/bin/env python3
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
2
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
3
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
4 # jp: a SAT command line tool
3136
9d0df638c8b4 dates update
Goffi <goffi@goffi.org>
parents: 3040
diff changeset
5 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org)
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
6 # Copyright (C) 2003-2016 Adrien Cossa (souliane@mailoo.org)
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
7
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
8 # This program is free software: you can redistribute it and/or modify
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
9 # it under the terms of the GNU Affero General Public License as published by
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
10 # the Free Software Foundation, either version 3 of the License, or
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
11 # (at your option) any later version.
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
12
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
13 # This program is distributed in the hope that it will be useful,
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
16 # GNU Affero General Public License for more details.
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
17
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
18 # You should have received a copy of the GNU Affero General Public License
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
20
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
21 from . import base
2893
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
22 from collections import OrderedDict
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
23 from sat.core.i18n import _
2893
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
24 from sat_frontends.jp.constants import Const as C
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
25 from sat_frontends.tools import jid
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
26 from sat.tools.common.ansi import ANSI as A
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
27
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
28 __commands__ = ["Roster"]
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
29
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
30
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
31 class Get(base.CommandBase):
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
32
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
33 def __init__(self, host):
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
34 super().__init__(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
35 host, 'get', use_output=C.OUTPUT_DICT, use_verbose=True,
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
36 extra_outputs = {"default": self.default_output},
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
37 help=_('retrieve the roster entities'))
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
38
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
39 def add_parser_options(self):
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
40 pass
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
41
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
42 def default_output(self, data):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
43 for contact_jid, contact_data in data.items():
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
44 all_keys = list(contact_data.keys())
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
45 keys_to_show = []
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
46 name = contact_data.get('name', contact_jid.node)
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
47
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
48 if self.verbosity >= 1:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
49 keys_to_show.append('groups')
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
50 all_keys.remove('groups')
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
51 if self.verbosity >= 2:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
52 keys_to_show.extend(all_keys)
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
53
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
54 if name is None:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
55 self.disp(A.color(C.A_HEADER, contact_jid))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
56 else:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
57 self.disp(A.color(C.A_HEADER, name, A.RESET, f" ({contact_jid})"))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
58 for k in keys_to_show:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
59 value = contact_data[k]
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
60 if value:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
61 if isinstance(value, list):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
62 value = ', '.join(value)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
63 self.disp(A.color(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
64 " ", C.A_SUBHEADER, f"{k}: ", A.RESET, str(value)))
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
65
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
66 async def start(self):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
67 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
68 contacts = await self.host.bridge.getContacts(profile_key=self.host.profile)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
69 except Exception as e:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
70 self.disp(f"error while retrieving the contacts: {e}", error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
71 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
72
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
73 contacts_dict = {}
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
74 for contact_jid_s, data, groups in contacts:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
75 # FIXME: we have to convert string to bool here for historical reason
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
76 # getContacts format should be changed and serialised properly
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
77 for key in ('from', 'to', 'ask'):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
78 if key in data:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
79 data[key] = C.bool(data[key])
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
80 data['groups'] = list(groups)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
81 contacts_dict[jid.JID(contact_jid_s)] = data
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
82
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
83 await self.output(contacts_dict)
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
84 self.host.quit()
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
85
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
86
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
87 class Stats(base.CommandBase):
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
88
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
89 def __init__(self, host):
1798
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
90 super(Stats, self).__init__(host, 'stats', help=_('Show statistics about a roster'))
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
91
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
92 def add_parser_options(self):
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
93 pass
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
94
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
95 async def start(self):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
96 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
97 contacts = await self.host.bridge.getContacts(profile_key=self.host.profile)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
98 except Exception as e:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
99 self.disp(f"error while retrieving the contacts: {e}", error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
100 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
101
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
102 hosts = {}
1798
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
103 unique_groups = set()
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
104 no_sub, no_from, no_to, no_group, total_group_subscription = 0, 0, 0, 0, 0
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
105 for contact, attrs, groups in contacts:
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
106 from_, to = C.bool(attrs["from"]), C.bool(attrs["to"])
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
107 if not from_:
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
108 if not to:
1798
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
109 no_sub += 1
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
110 else:
1798
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
111 no_from += 1
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
112 elif not to:
1798
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
113 no_to += 1
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
114
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
115 host = jid.JID(contact).domain
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
116
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
117 hosts.setdefault(host, 0)
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
118 hosts[host] += 1
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
119 if groups:
1798
c5d58387d031 jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents: 1797
diff changeset
120 unique_groups.update(groups)
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
121 total_group_subscription += len(groups)
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
122 if not groups:
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
123 no_group += 1
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
124 hosts = OrderedDict(sorted(list(hosts.items()), key=lambda item:-item[1]))
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
125
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
126 print()
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
127 print("Total number of contacts: %d" % len(contacts))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
128 print("Number of different hosts: %d" % len(hosts))
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
129 print()
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
130 for host, count in hosts.items():
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
131 print("Contacts on {host}: {count} ({rate:.1f}%)".format(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
132 host=host, count=count, rate=100 * float(count) / len(contacts)))
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
133 print()
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
134 print("Contacts with no 'from' subscription: %d" % no_from)
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
135 print("Contacts with no 'to' subscription: %d" % no_to)
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
136 print("Contacts with no subscription at all: %d" % no_sub)
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
137 print()
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
138 print("Total number of groups: %d" % len(unique_groups))
1932
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
139 try:
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
140 contacts_per_group = float(total_group_subscription) / len(unique_groups)
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
141 except ZeroDivisionError:
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
142 contacts_per_group = 0
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
143 print("Average contacts per group: {:.1f}".format(contacts_per_group))
1932
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
144 try:
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
145 groups_per_contact = float(total_group_subscription) / len(contacts)
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
146 except ZeroDivisionError:
44342730df66 jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents: 1864
diff changeset
147 groups_per_contact = 0
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
148 print(f"Average groups' subscriptions per contact: {groups_per_contact:.1f}")
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
149 print("Contacts not assigned to any group: %d" % no_group)
1796
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
150 self.host.quit()
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
151
314d2eb7fbaa jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents: 1793
diff changeset
152
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
153 class Purge(base.CommandBase):
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
154
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
155 def __init__(self, host):
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
156 super(Purge, self).__init__(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
157 host, 'purge',
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
158 help=_('purge the roster from its contacts with no subscription'))
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
159
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
160 def add_parser_options(self):
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
161 self.parser.add_argument(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
162 "--no_from", action="store_true",
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
163 help=_("also purge contacts with no 'from' subscription"))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
164 self.parser.add_argument(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
165 "--no_to", action="store_true",
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
166 help=_("also purge contacts with no 'to' subscription"))
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
167
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
168 async def start(self):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
169 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
170 contacts = await self.host.bridge.getContacts(self.host.profile)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
171 except Exception as e:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
172 self.disp(f"error while retrieving the contacts: {e}", error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
173 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
174
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
175 no_sub, no_from, no_to = [], [], []
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
176 for contact, attrs, groups in contacts:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
177 from_, to = C.bool(attrs["from"]), C.bool(attrs["to"])
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
178 if not from_:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
179 if not to:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
180 no_sub.append(contact)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
181 elif self.args.no_from:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
182 no_from.append(contact)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
183 elif not to and self.args.no_to:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
184 no_to.append(contact)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
185 if not no_sub and not no_from and not no_to:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
186 self.disp(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
187 f"Nothing to do - there's a from and/or to subscription(s) between "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
188 f"profile {self.host.profile!r} and each of its contacts"
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
189 )
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
190 elif await self.ask_confirmation(no_sub, no_from, no_to):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
191 for contact in no_sub + no_from + no_to:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
192 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
193 await self.host.bridge.delContact(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
194 contact, profile_key=self.host.profile)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
195 except Exception as e:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
196 self.disp(f"can't delete contact {contact!r}: {e}", error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
197 else:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
198 self.disp(f"contact {contact!r} has been removed")
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
199
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
200 self.host.quit()
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
201
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
202 async def ask_confirmation(self, no_sub, no_from, no_to):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
203 """Ask the confirmation before removing contacts.
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
204
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
205 @param no_sub (list[unicode]): list of contacts with no subscription
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
206 @param no_from (list[unicode]): list of contacts with no 'from' subscription
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
207 @param no_to (list[unicode]): list of contacts with no 'to' subscription
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
208 @return bool
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
209 """
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
210 if no_sub:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
211 self.disp(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
212 f"There's no subscription between profile {self.host.profile!r} and the "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
213 f"following contacts:")
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
214 self.disp(" " + "\n ".join(no_sub))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
215 if no_from:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
216 self.disp(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
217 f"There's no 'from' subscription between profile {self.host.profile!r} "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
218 f"and the following contacts:")
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
219 self.disp(" " + "\n ".join(no_from))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
220 if no_to:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
221 self.disp(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
222 f"There's no 'to' subscription between profile {self.host.profile!r} and "
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
223 f"the following contacts:")
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
224 self.disp(" " + "\n ".join(no_to))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
225 message = f"REMOVE them from profile {self.host.profile}'s roster"
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
226 while True:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
227 res = await self.host.ainput(f"{message} (y/N)? ")
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
228 if not res or res.lower() == 'n':
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
229 return False
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
230 if res.lower() == 'y':
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
231 return True
1799
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
232
f1f4775f8cc0 jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents: 1798
diff changeset
233
2893
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
234 class Resync(base.CommandBase):
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
235
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
236 def __init__(self, host):
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
237 super(Resync, self).__init__(
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2893
diff changeset
238 host, 'resync', help=_('do a full resynchronisation of roster with server'))
2893
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
239
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
240 def add_parser_options(self):
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
241 pass
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
242
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
243 async def start(self):
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
244 try:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
245 await self.host.bridge.rosterResync(profile_key=self.host.profile)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
246 except Exception as e:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
247 self.disp(f"can't resynchronise roster: {e}", error=True)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
248 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
249 else:
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
250 self.disp(_("Roster resynchronized"))
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
251 self.host.quit(C.EXIT_OK)
2893
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
252
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
253
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
254 class Roster(base.CommandBase):
2893
7c8773723200 jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents: 2771
diff changeset
255 subcommands = (Get, Stats, Purge, Resync)
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
256
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
257 def __init__(self, host):
3040
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
258 super(Roster, self).__init__(
fee60f17ebac jp: jp asyncio port:
Goffi <goffi@goffi.org>
parents: 3028
diff changeset
259 host, 'roster', use_profile=True, help=_("Manage an entity's roster"))