annotate sat_frontends/jp/cmd_roster.py @ 3040:fee60f17ebac

jp: jp asyncio port: /!\ this commit is huge. Jp is temporarily not working with `dbus` bridge /!\ This patch implements the port of jp to asyncio, so it is now correctly using the bridge asynchronously, and it can be used with bridges like `pb`. This also simplify the code, notably for things which were previously implemented with many callbacks (like pagination with RSM). During the process, some behaviours have been modified/fixed, in jp and backends, check diff for details.
author Goffi <goffi@goffi.org>
date Wed, 25 Sep 2019 08:56:41 +0200
parents ab2696e34d29
children 9d0df638c8b4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1960
3e168cde7a7d jp: fixed shebang python call
Goffi <goffi@goffi.org>
parents: 1932
diff changeset
1 #!/usr/bin/env python2
1793
f39ca2832774 jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
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
2771
003b8b4b56a7 date update
Goffi <goffi@goffi.org>
parents: 2765
diff changeset
5 # Copyright (C) 2009-2019 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"))