Mercurial > libervia-backend
annotate libervia/cli/cmd_roster.py @ 4306:94e0968987cd
plugin XEP-0033: code modernisation, improve delivery, data validation:
- Code has been rewritten using Pydantic models and `async` coroutines for data validation
and cleaner element parsing/generation.
- Delivery has been completely rewritten. It now works even if server doesn't support
multicast, and send to local multicast service first. Delivering to local multicast
service first is due to bad support of XEP-0033 in server (notably Prosody which has an
incomplete implementation), and the current impossibility to detect if a sub-domain
service handles fully multicast or only for local domains. This is a workaround to have
a good balance between backward compatilibity and use of bandwith, and to make it work
with the incoming email gateway implementation (the gateway will only deliver to
entities of its own domain).
- disco feature checking now uses `async` corountines. `host` implementation still use
Deferred return values for compatibility with legacy code.
rel 450
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 26 Sep 2024 16:12:01 +0200 |
parents | 0d7bb4df2343 |
children |
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__( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
34 host, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
35 "get", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
36 use_output=C.OUTPUT_DICT, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
37 use_verbose=True, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
38 extra_outputs={"default": self.default_output}, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
39 help=_("retrieve the roster entities"), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
40 ) |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
41 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
42 def add_parser_options(self): |
3040 | 43 pass |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
44 |
3040 | 45 def default_output(self, data): |
46 for contact_jid, contact_data in data.items(): | |
47 all_keys = list(contact_data.keys()) | |
48 keys_to_show = [] | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
49 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
|
50 |
3040 | 51 if self.verbosity >= 1: |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
52 keys_to_show.append("groups") |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
53 all_keys.remove("groups") |
3040 | 54 if self.verbosity >= 2: |
55 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
|
56 |
3040 | 57 if name is None: |
58 self.disp(A.color(C.A_HEADER, contact_jid)) | |
59 else: | |
60 self.disp(A.color(C.A_HEADER, name, A.RESET, f" ({contact_jid})")) | |
61 for k in keys_to_show: | |
62 value = contact_data[k] | |
63 if value: | |
64 if isinstance(value, list): | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
65 value = ", ".join(value) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
66 self.disp( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
67 A.color(" ", C.A_SUBHEADER, f"{k}: ", A.RESET, str(value)) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
68 ) |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
69 |
3040 | 70 async def start(self): |
71 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
72 contacts = await self.host.bridge.contacts_get(profile_key=self.host.profile) |
3040 | 73 except Exception as e: |
74 self.disp(f"error while retrieving the contacts: {e}", error=True) | |
75 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
|
76 |
3040 | 77 contacts_dict = {} |
78 for contact_jid_s, data, groups in contacts: | |
79 # 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
|
80 # contacts_get format should be changed and serialised properly |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
81 for key in ("from", "to", "ask"): |
3040 | 82 if key in data: |
83 data[key] = C.bool(data[key]) | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
84 data["groups"] = list(groups) |
3040 | 85 contacts_dict[jid.JID(contact_jid_s)] = data |
86 | |
87 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
|
88 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
|
89 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
90 |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
91 class Set(base.CommandBase): |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
92 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
93 def __init__(self, host): |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
94 super().__init__(host, "set", help=_("set metadata for a roster entity")) |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
95 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
96 def add_parser_options(self): |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
97 self.parser.add_argument( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
98 "-n", "--name", default="", help=_("name to use for this entity") |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
99 ) |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
100 self.parser.add_argument( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
101 "-g", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
102 "--group", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
103 dest="groups", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
104 action="append", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
105 metavar="GROUP", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
106 default=[], |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
107 help=_("groups for this entity"), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
108 ) |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
109 self.parser.add_argument( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
110 "-R", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
111 "--replace", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
112 action="store_true", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
113 help=_("replace all metadata instead of adding them"), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
114 ) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
115 self.parser.add_argument("jid", help=_("jid of the roster entity")) |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
116 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
117 async def start(self): |
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 if self.args.replace: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
120 name = self.args.name |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
121 groups = self.args.groups |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
122 else: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
123 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
124 entity_data = await self.host.bridge.contact_get( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
125 self.args.jid, self.host.profile |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
126 ) |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
127 except Exception as e: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
128 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
|
129 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
130 name = self.args.name or entity_data[0].get("name") or "" |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
131 groups = set(entity_data[1]) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
132 groups = list(groups.union(self.args.groups)) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
133 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
134 try: |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
135 await self.host.bridge.contact_update( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
136 self.args.jid, name, groups, self.host.profile |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
137 ) |
3255
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
138 except Exception as e: |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
139 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
|
140 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
141 self.host.quit() |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
142 |
012e89fb2dd1
jp (roster): new roster/set command
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
143 |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
144 class Delete(base.CommandBase): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
145 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
146 def __init__(self, host): |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
147 super().__init__(host, "delete", help=_("remove an entity from roster")) |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
148 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
149 def add_parser_options(self): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
150 self.parser.add_argument( |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
151 "-f", "--force", action="store_true", help=_("delete without confirmation") |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
152 ) |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
153 self.parser.add_argument("jid", help=_("jid of the roster entity")) |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
154 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
155 async def start(self): |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
156 if not self.args.force: |
3970
4c3361e2bf55
cli (file/send): add `--encrypt` argument to request encryption:
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
157 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
|
158 entity=self.args.jid |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
159 ) |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
160 await self.host.confirm_or_quit(message, _("entity deletion cancelled")) |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
161 try: |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
162 await self.host.bridge.contact_del(self.args.jid, self.host.profile) |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
163 except Exception as e: |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
164 self.disp(f"error while deleting the entity: {e}", error=True) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
165 self.host.quit(C.EXIT_BRIDGE_ERRBACK) |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
166 self.host.quit() |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
167 |
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
168 |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
169 class Stats(base.CommandBase): |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
170 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
171 def __init__(self, host): |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
172 super(Stats, self).__init__( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
173 host, "stats", help=_("Show statistics about a roster") |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
174 ) |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
175 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
176 def add_parser_options(self): |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
177 pass |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
178 |
3040 | 179 async def start(self): |
180 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
181 contacts = await self.host.bridge.contacts_get(profile_key=self.host.profile) |
3040 | 182 except Exception as e: |
183 self.disp(f"error while retrieving the contacts: {e}", error=True) | |
184 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
185 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
186 hosts = {} |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
187 unique_groups = set() |
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
188 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
|
189 for contact, attrs, groups in contacts: |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
190 from_, to = C.bool(attrs["from"]), C.bool(attrs["to"]) |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
191 if not from_: |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
192 if not to: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
193 no_sub += 1 |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
194 else: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
195 no_from += 1 |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
196 elif not to: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
197 no_to += 1 |
3040 | 198 |
199 host = jid.JID(contact).domain | |
200 | |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
201 hosts.setdefault(host, 0) |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
202 hosts[host] += 1 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
203 if groups: |
1798
c5d58387d031
jp (roster stats): add some extra information
souliane <souliane@mailoo.org>
parents:
1797
diff
changeset
|
204 unique_groups.update(groups) |
1796
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
205 total_group_subscription += len(groups) |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
206 if not groups: |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
207 no_group += 1 |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
208 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
|
209 |
3028 | 210 print() |
211 print("Total number of contacts: %d" % len(contacts)) | |
212 print("Number of different hosts: %d" % len(hosts)) | |
213 print() | |
214 for host, count in hosts.items(): | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
215 print( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
216 "Contacts on {host}: {count} ({rate:.1f}%)".format( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
217 host=host, count=count, rate=100 * float(count) / len(contacts) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
218 ) |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
219 ) |
3028 | 220 print() |
221 print("Contacts with no 'from' subscription: %d" % no_from) | |
222 print("Contacts with no 'to' subscription: %d" % no_to) | |
223 print("Contacts with no subscription at all: %d" % no_sub) | |
224 print() | |
225 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
|
226 try: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
227 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
|
228 except ZeroDivisionError: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
229 contacts_per_group = 0 |
3028 | 230 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
|
231 try: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
232 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
|
233 except ZeroDivisionError: |
44342730df66
jp (cmd/roster): fixes division by zero exceptions
souliane <souliane@mailoo.org>
parents:
1864
diff
changeset
|
234 groups_per_contact = 0 |
3040 | 235 print(f"Average groups' subscriptions per contact: {groups_per_contact:.1f}") |
3028 | 236 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
|
237 self.host.quit() |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
238 |
314d2eb7fbaa
jp: add command "roster stats"
souliane <souliane@mailoo.org>
parents:
1793
diff
changeset
|
239 |
3040 | 240 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
|
241 |
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
242 def __init__(self, host): |
3040 | 243 super(Purge, self).__init__( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
244 host, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
245 "purge", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
246 help=_("purge the roster from its contacts with no subscription"), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
247 ) |
1799
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
248 |
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
249 def add_parser_options(self): |
3040 | 250 self.parser.add_argument( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
251 "--no-from", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
252 action="store_true", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
253 help=_("also purge contacts with no 'from' subscription"), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
254 ) |
3040 | 255 self.parser.add_argument( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
256 "--no-to", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
257 action="store_true", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
258 help=_("also purge contacts with no 'to' subscription"), |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
259 ) |
1799
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
260 |
3040 | 261 async def start(self): |
262 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
263 contacts = await self.host.bridge.contacts_get(self.host.profile) |
3040 | 264 except Exception as e: |
265 self.disp(f"error while retrieving the contacts: {e}", error=True) | |
266 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
|
267 |
3040 | 268 no_sub, no_from, no_to = [], [], [] |
269 for contact, attrs, groups in contacts: | |
270 from_, to = C.bool(attrs["from"]), C.bool(attrs["to"]) | |
271 if not from_: | |
272 if not to: | |
273 no_sub.append(contact) | |
274 elif self.args.no_from: | |
275 no_from.append(contact) | |
276 elif not to and self.args.no_to: | |
277 no_to.append(contact) | |
278 if not no_sub and not no_from and not no_to: | |
279 self.disp( | |
280 f"Nothing to do - there's a from and/or to subscription(s) between " | |
281 f"profile {self.host.profile!r} and each of its contacts" | |
282 ) | |
283 elif await self.ask_confirmation(no_sub, no_from, no_to): | |
284 for contact in no_sub + no_from + no_to: | |
285 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
286 await self.host.bridge.contact_del( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
287 contact, profile_key=self.host.profile |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
288 ) |
3040 | 289 except Exception as e: |
290 self.disp(f"can't delete contact {contact!r}: {e}", error=True) | |
291 else: | |
292 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
|
293 |
3040 | 294 self.host.quit() |
295 | |
296 async def ask_confirmation(self, no_sub, no_from, no_to): | |
297 """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
|
298 |
3040 | 299 @param no_sub (list[unicode]): list of contacts with no subscription |
300 @param no_from (list[unicode]): list of contacts with no 'from' subscription | |
301 @param no_to (list[unicode]): list of contacts with no 'to' subscription | |
302 @return bool | |
1799
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
303 """ |
3040 | 304 if no_sub: |
305 self.disp( | |
306 f"There's no subscription between profile {self.host.profile!r} and the " | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
307 f"following contacts:" |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
308 ) |
3040 | 309 self.disp(" " + "\n ".join(no_sub)) |
310 if no_from: | |
311 self.disp( | |
312 f"There's no 'from' subscription between profile {self.host.profile!r} " | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
313 f"and the following contacts:" |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
314 ) |
3040 | 315 self.disp(" " + "\n ".join(no_from)) |
316 if no_to: | |
317 self.disp( | |
318 f"There's no 'to' subscription between profile {self.host.profile!r} and " | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
319 f"the following contacts:" |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
320 ) |
3040 | 321 self.disp(" " + "\n ".join(no_to)) |
322 message = f"REMOVE them from profile {self.host.profile}'s roster" | |
323 while True: | |
324 res = await self.host.ainput(f"{message} (y/N)? ") | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
325 if not res or res.lower() == "n": |
3040 | 326 return False |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
327 if res.lower() == "y": |
3040 | 328 return True |
1799
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
329 |
f1f4775f8cc0
jp (roster): add command "roster get" with parameters "--subscriptions", "--name" and "--groups"
souliane <souliane@mailoo.org>
parents:
1798
diff
changeset
|
330 |
2893
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
331 class Resync(base.CommandBase): |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
332 |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
333 def __init__(self, host): |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
334 super(Resync, self).__init__( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
335 host, "resync", help=_("do a full resynchronisation of roster with server") |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
336 ) |
2893
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
337 |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
338 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
|
339 pass |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
340 |
3040 | 341 async def start(self): |
342 try: | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3970
diff
changeset
|
343 await self.host.bridge.roster_resync(profile_key=self.host.profile) |
3040 | 344 except Exception as e: |
345 self.disp(f"can't resynchronise roster: {e}", error=True) | |
346 self.host.quit(C.EXIT_BRIDGE_ERRBACK) | |
347 else: | |
348 self.disp(_("Roster resynchronized")) | |
349 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
|
350 |
7c8773723200
jp (roster): added resync command to do a full roster resynchronisation
Goffi <goffi@goffi.org>
parents:
2771
diff
changeset
|
351 |
1793
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
352 class Roster(base.CommandBase): |
3414
ffe7a6d6018a
jp (roster): `delete` implementation
Goffi <goffi@goffi.org>
parents:
3411
diff
changeset
|
353 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
|
354 |
f39ca2832774
jp: add command "roster purge" to remove the contacts with no from/to subscription
souliane <souliane@mailoo.org>
parents:
diff
changeset
|
355 def __init__(self, host): |
3040 | 356 super(Roster, self).__init__( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
357 host, "roster", use_profile=True, help=_("Manage an entity's roster") |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4075
diff
changeset
|
358 ) |