Mercurial > libervia-backend
annotate libervia/cli/cmd_roster.py @ 4219:1b5cf2ee1d86
plugin XEP-0384, XEP-0391: download missing devices list:
when a peer jid was not in our roster, devices list was not retrieved, resulting in failed
en/decryption. This patch does check it and download missing devices list in necessary.
There is no subscription managed yet, so the list won't be updated in case of new devices,
this should be addressed at some point.
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 05 Mar 2024 17:31:36 +0100 |
parents | 47401850dec6 |
children | 0d7bb4df2343 |
rev | line source |
---|---|
3137 | 1 #!/usr/bin/env python3 |
2 | |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
3 # Libervia CLI |
3479 | 4 # Copyright (C) 2009-2021 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
|
5 # 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
|
6 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
7 # 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
|
8 # 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
|
9 # 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
|
10 # (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
|
11 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
12 # 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
|
13 # 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
|
14 # 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
|
15 # 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
|
16 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
17 # 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
|
18 # 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
|
19 |
3028 | 20 from . import base |
2893
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
21 from collections import OrderedDict |
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
22 from libervia.backend.core.i18n import _ |
4075
47401850dec6
refactoring: rename `libervia.frontends.jp` to `libervia.cli`
Goffi <goffi@goffi.org>
parents:
4074
diff
changeset
|
23 from libervia.cli.constants import Const as C |
4074
26b7ed2817da
refactoring: rename `sat_frontends` to `libervia.frontends`
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
24 from libervia.frontends.tools import jid |
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
25 from libervia.backend.tools.common.ansi import ANSI as A |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
26 |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
27 __commands__ = ["Roster"] |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
28 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
29 |
3040 | 30 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
|
31 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
32 def __init__(self, host): |
3040 | 33 super().__init__( |
34 host, 'get', use_output=C.OUTPUT_DICT, use_verbose=True, | |
35 extra_outputs = {"default": self.default_output}, | |
36 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
|
37 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
38 def add_parser_options(self): |
3040 | 39 pass |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
40 |
3040 | 41 def default_output(self, data): |
42 for contact_jid, contact_data in data.items(): | |
43 all_keys = list(contact_data.keys()) | |
44 keys_to_show = [] | |
45 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
|
46 |
3040 | 47 if self.verbosity >= 1: |
48 keys_to_show.append('groups') | |
49 all_keys.remove('groups') | |
50 if self.verbosity >= 2: | |
51 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
|
52 |
3040 | 53 if name is None: |
54 self.disp(A.color(C.A_HEADER, contact_jid)) | |
55 else: | |
56 self.disp(A.color(C.A_HEADER, name, A.RESET, f" ({contact_jid})")) | |
57 for k in keys_to_show: | |
58 value = contact_data[k] | |
59 if value: | |
60 if isinstance(value, list): | |
61 value = ', '.join(value) | |
62 self.disp(A.color( | |
63 " ", 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
|
64 |
3040 | 65 async def start(self): |
66 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
67 contacts = await self.host.bridge.contacts_get(profile_key=self.host.profile) |
3040 | 68 except Exception as e: |
69 self.disp(f"error while retrieving the contacts: {e}", error=True) | |
70 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
|
71 |
3040 | 72 contacts_dict = {} |
73 for contact_jid_s, data, groups in contacts: | |
74 # FIXME: we have to convert string to bool here for historical reason | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
75 # contacts_get format should be changed and serialised properly |
3040 | 76 for key in ('from', 'to', 'ask'): |
77 if key in data: | |
78 data[key] = C.bool(data[key]) | |
79 data['groups'] = list(groups) | |
80 contacts_dict[jid.JID(contact_jid_s)] = data | |
81 | |
82 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
|
83 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
|
84 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
85 |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
86 class Set(base.CommandBase): |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
87 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
88 def __init__(self, host): |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
89 super().__init__(host, 'set', help=_('set metadata for a roster entity')) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
90 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
91 def add_parser_options(self): |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
92 self.parser.add_argument( |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
93 "-n", "--name", default="", help=_('name to use for this entity')) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
94 self.parser.add_argument( |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
95 "-g", "--group", dest='groups', action='append', metavar='GROUP', default=[], |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
96 help=_('groups for this entity')) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
97 self.parser.add_argument( |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
98 "-R", "--replace", action="store_true", |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
99 help=_("replace all metadata instead of adding them")) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
100 self.parser.add_argument( |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
101 "jid", help=_("jid of the roster entity")) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
102 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
103 async def start(self): |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
104 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
105 if self.args.replace: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
106 name = self.args.name |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
107 groups = self.args.groups |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
108 else: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
109 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
110 entity_data = await self.host.bridge.contact_get( |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
111 self.args.jid, self.host.profile) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
112 except Exception as e: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
113 self.disp(f"error while retrieving the contact: {e}", error=True) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
114 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
115 name = self.args.name or entity_data[0].get('name') or '' |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
116 groups = set(entity_data[1]) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
117 groups = list(groups.union(self.args.groups)) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
118 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
119 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
120 await self.host.bridge.contact_update( |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
121 self.args.jid, name, groups, self.host.profile) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
122 except Exception as e: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
123 self.disp(f"error while updating the contact: {e}", error=True) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
124 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
125 self.host.quit() |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
126 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
127 |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
128 class Delete(base.CommandBase): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
129 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
130 def __init__(self, host): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
131 super().__init__(host, 'delete', help=_('remove an entity from roster')) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
132 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
133 def add_parser_options(self): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
134 self.parser.add_argument( |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
135 "-f", "--force", action="store_true", help=_("delete without confirmation") |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
136 ) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
137 self.parser.add_argument( |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
138 "jid", help=_("jid of the roster entity")) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
139 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
140 async def start(self): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
141 if not self.args.force: |
3970
4c3361e2bf55
cli (file/send): add `--encrypt` argument to request encryption:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
142 message = _("Are you sure to delete {entity} from your roster?").format( |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
143 entity=self.args.jid |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
144 ) |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
145 await self.host.confirm_or_quit(message, _("entity deletion cancelled")) |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
146 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
147 await self.host.bridge.contact_del( |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
148 self.args.jid, self.host.profile) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
149 except Exception as e: |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
150 self.disp(f"error while deleting the entity: {e}", error=True) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
151 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
152 self.host.quit() |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
153 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
154 |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
155 class Stats(base.CommandBase): |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
156 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
157 def __init__(self, host): |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
158 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
|
159 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
160 def add_parser_options(self): |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
161 pass |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
162 |
3040 | 163 async def start(self): |
164 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
165 contacts = await self.host.bridge.contacts_get(profile_key=self.host.profile) |
3040 | 166 except Exception as e: |
167 self.disp(f"error while retrieving the contacts: {e}", error=True) | |
168 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
169 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
170 hosts = {} |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
171 unique_groups = set() |
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
172 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
|
173 for contact, attrs, groups in contacts: |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
174 from_, to = C.bool(attrs["from"]), C.bool(attrs["to"]) |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
175 if not from_: |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
176 if not to: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
177 no_sub += 1 |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
178 else: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
179 no_from += 1 |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
180 elif not to: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
181 no_to += 1 |
3040 | 182 |
183 host = jid.JID(contact).domain | |
184 | |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
185 hosts.setdefault(host, 0) |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
186 hosts[host] += 1 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
187 if groups: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
188 unique_groups.update(groups) |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
189 total_group_subscription += len(groups) |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
190 if not groups: |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
191 no_group += 1 |
3028 | 192 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
|
193 |
3028 | 194 print() |
195 print("Total number of contacts: %d" % len(contacts)) | |
196 print("Number of different hosts: %d" % len(hosts)) | |
197 print() | |
198 for host, count in hosts.items(): | |
3040 | 199 print("Contacts on {host}: {count} ({rate:.1f}%)".format( |
200 host=host, count=count, rate=100 * float(count) / len(contacts))) | |
3028 | 201 print() |
202 print("Contacts with no 'from' subscription: %d" % no_from) | |
203 print("Contacts with no 'to' subscription: %d" % no_to) | |
204 print("Contacts with no subscription at all: %d" % no_sub) | |
205 print() | |
206 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
|
207 try: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
208 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
|
209 except ZeroDivisionError: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
210 contacts_per_group = 0 |
3028 | 211 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
|
212 try: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
213 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
|
214 except ZeroDivisionError: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
215 groups_per_contact = 0 |
3040 | 216 print(f"Average groups' subscriptions per contact: {groups_per_contact:.1f}") |
3028 | 217 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
|
218 self.host.quit() |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
219 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
220 |
3040 | 221 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
|
222 |
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
223 def __init__(self, host): |
3040 | 224 super(Purge, self).__init__( |
225 host, 'purge', | |
226 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
|
227 |
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
228 def add_parser_options(self): |
3040 | 229 self.parser.add_argument( |
3411
f30b238d9c45
jp: follow best practices and use a dash (`-`) instead of underscore (`_`) for long options.
Goffi <goffi@goffi.org>
parents:
3255
diff
changeset
|
230 "--no-from", action="store_true", |
3040 | 231 help=_("also purge contacts with no 'from' subscription")) |
232 self.parser.add_argument( | |
3411
f30b238d9c45
jp: follow best practices and use a dash (`-`) instead of underscore (`_`) for long options.
Goffi <goffi@goffi.org>
parents:
3255
diff
changeset
|
233 "--no-to", action="store_true", |
3040 | 234 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
|
235 |
3040 | 236 async def start(self): |
237 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
238 contacts = await self.host.bridge.contacts_get(self.host.profile) |
3040 | 239 except Exception as e: |
240 self.disp(f"error while retrieving the contacts: {e}", error=True) | |
241 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
|
242 |
3040 | 243 no_sub, no_from, no_to = [], [], [] |
244 for contact, attrs, groups in contacts: | |
245 from_, to = C.bool(attrs["from"]), C.bool(attrs["to"]) | |
246 if not from_: | |
247 if not to: | |
248 no_sub.append(contact) | |
249 elif self.args.no_from: | |
250 no_from.append(contact) | |
251 elif not to and self.args.no_to: | |
252 no_to.append(contact) | |
253 if not no_sub and not no_from and not no_to: | |
254 self.disp( | |
255 f"Nothing to do - there's a from and/or to subscription(s) between " | |
256 f"profile {self.host.profile!r} and each of its contacts" | |
257 ) | |
258 elif await self.ask_confirmation(no_sub, no_from, no_to): | |
259 for contact in no_sub + no_from + no_to: | |
260 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
261 await self.host.bridge.contact_del( |
3040 | 262 contact, profile_key=self.host.profile) |
263 except Exception as e: | |
264 self.disp(f"can't delete contact {contact!r}: {e}", error=True) | |
265 else: | |
266 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
|
267 |
3040 | 268 self.host.quit() |
269 | |
270 async def ask_confirmation(self, no_sub, no_from, no_to): | |
271 """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
|
272 |
3040 | 273 @param no_sub (list[unicode]): list of contacts with no subscription |
274 @param no_from (list[unicode]): list of contacts with no 'from' subscription | |
275 @param no_to (list[unicode]): list of contacts with no 'to' subscription | |
276 @return bool | |
1799
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
277 """ |
3040 | 278 if no_sub: |
279 self.disp( | |
280 f"There's no subscription between profile {self.host.profile!r} and the " | |
281 f"following contacts:") | |
282 self.disp(" " + "\n ".join(no_sub)) | |
283 if no_from: | |
284 self.disp( | |
285 f"There's no 'from' subscription between profile {self.host.profile!r} " | |
286 f"and the following contacts:") | |
287 self.disp(" " + "\n ".join(no_from)) | |
288 if no_to: | |
289 self.disp( | |
290 f"There's no 'to' subscription between profile {self.host.profile!r} and " | |
291 f"the following contacts:") | |
292 self.disp(" " + "\n ".join(no_to)) | |
293 message = f"REMOVE them from profile {self.host.profile}'s roster" | |
294 while True: | |
295 res = await self.host.ainput(f"{message} (y/N)? ") | |
296 if not res or res.lower() == 'n': | |
297 return False | |
298 if res.lower() == 'y': | |
299 return True | |
1799
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
300 |
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
301 |
2893
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
302 class Resync(base.CommandBase): |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
303 |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
304 def __init__(self, host): |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
305 super(Resync, self).__init__( |
3028 | 306 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
|
307 |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
308 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
|
309 pass |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
310 |
3040 | 311 async def start(self): |
312 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
313 await self.host.bridge.roster_resync(profile_key=self.host.profile) |
3040 | 314 except Exception as e: |
315 self.disp(f"can't resynchronise roster: {e}", error=True) | |
316 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
317 else: | |
318 self.disp(_("Roster resynchronized")) | |
319 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
|
320 |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
321 |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
322 class Roster(base.CommandBase): |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
323 subcommands = (Get, Set, Delete, 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
|
324 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
325 def __init__(self, host): |
3040 | 326 super(Roster, self).__init__( |
327 host, 'roster', use_profile=True, help=_("Manage an entity's roster")) |