Mercurial > libervia-backend
annotate libervia/cli/cmd_call.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 | 9218d4331bb2 |
children | d01b8d002619 |
rev | line source |
---|---|
4143 | 1 #!/usr/bin/env python3 |
2 | |
3 | |
4 # Libervia CLI | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 from functools import partial | |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
22 import importlib |
4143 | 23 import logging |
24 | |
25 | |
26 from libervia.backend.core.i18n import _ | |
27 from libervia.backend.tools.common import data_format | |
28 from libervia.cli.constants import Const as C | |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
29 from libervia.frontends.tools import jid |
4143 | 30 |
31 from . import base | |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
32 from .call_webrtc import CallData, WebRTCCall |
4143 | 33 |
34 __commands__ = ["Call"] | |
35 | |
36 | |
37 class Common(base.CommandBase): | |
38 | |
4206 | 39 |
40 def __init__(self, *args, **kwargs): | |
41 super().__init__( | |
42 *args, | |
43 use_output=C.OUTPUT_CUSTOM, | |
44 extra_outputs={ | |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
45 #: automatically select best output for current platform |
4206 | 46 "default": self.auto_output, |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
47 #: simple output with GStreamer ``autovideosink`` |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
48 "simple": partial(self.use_output, "simple"), |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
49 #: Qt GUI |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
50 "gui": partial(self.use_output, "gui"), |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
51 #: experimental TUI output |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
52 "tui": partial(self.use_output, "tui"), |
4206 | 53 }, |
54 **kwargs | |
55 ) | |
56 | |
4143 | 57 def add_parser_options(self): |
58 self.parser.add_argument( | |
59 "--no-ui", action="store_true", help=_("disable user interface") | |
60 ) | |
61 | |
62 async def start(self): | |
63 root_logger = logging.getLogger() | |
64 # we don't want any formatting for messages from webrtc | |
65 for handler in root_logger.handlers: | |
66 handler.setFormatter(None) | |
67 if self.verbosity == 0: | |
68 root_logger.setLevel(logging.ERROR) | |
69 if self.verbosity >= 1: | |
70 root_logger.setLevel(logging.WARNING) | |
71 if self.verbosity >= 2: | |
72 root_logger.setLevel(logging.DEBUG) | |
73 | |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
74 async def auto_output(self, call_data: CallData) -> None: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
75 """Make a guess on the best output to use on current platform""" |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
76 try: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
77 from .call_gui import AVCallUI |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
78 except ImportError: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
79 # we can't import GUI, we may have missing modules |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
80 await self.use_output("simple", call_data) |
4206 | 81 else: |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
82 if AVCallUI.can_run(): |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
83 await self.use_output("gui", call_data) |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
84 else: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
85 await self.use_output("simple", call_data) |
4206 | 86 |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
87 async def use_output(self, output_type, call_data: CallData): |
4206 | 88 try: |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
89 AVCall_module = importlib.import_module(f"libervia.cli.call_{output_type}") |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
90 AVCallUI = AVCall_module.AVCallUI |
4206 | 91 except Exception as e: |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
92 self.disp(f"Error starting {output_type.upper()} UI: {e}", error=True) |
4206 | 93 self.host.quit(C.EXIT_ERROR) |
4210
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
94 else: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
95 try: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
96 await AVCallUI.run(self, call_data) |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
97 except Exception as e: |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
98 self.disp(f"Error running {output_type.upper()} UI: {e}", error=True) |
9218d4331bb2
cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
4206
diff
changeset
|
99 self.host.quit(C.EXIT_ERROR) |
4206 | 100 |
4143 | 101 |
102 class Make(Common): | |
103 def __init__(self, host): | |
104 super().__init__( | |
105 host, | |
106 "make", | |
107 use_verbose=True, | |
108 help=_("start a call"), | |
109 ) | |
110 | |
111 def add_parser_options(self): | |
112 super().add_parser_options() | |
113 self.parser.add_argument( | |
114 "entity", | |
115 metavar="JID", | |
116 help=_("JIDs of entity to call"), | |
117 ) | |
118 | |
119 async def start(self): | |
120 await super().start() | |
4206 | 121 await super().output(CallData( |
122 callee=jid.JID(self.args.entity), | |
123 )) | |
4143 | 124 |
125 | |
126 class Receive(Common): | |
127 def __init__(self, host): | |
128 super().__init__( | |
129 host, | |
130 "receive", | |
131 use_verbose=True, | |
132 help=_("wait for a call"), | |
133 ) | |
134 | |
135 def add_parser_options(self): | |
136 super().add_parser_options() | |
137 auto_accept_group = self.parser.add_mutually_exclusive_group() | |
138 auto_accept_group.add_argument( | |
139 "-a", | |
140 "--auto-accept", | |
141 action="append", | |
142 metavar="JID", | |
143 default=[], | |
144 help=_("automatically accept call from this jid (can be used multiple times)") | |
145 ) | |
146 auto_accept_group.add_argument( | |
147 "--auto-accept-all", | |
148 action="store_true", | |
149 help=_("automatically accept call from anybody") | |
150 ) | |
151 | |
152 async def on_action_new( | |
153 self, action_data_s: str, action_id: str, security_limit: int, profile: str | |
154 ) -> None: | |
155 if profile != self.profile: | |
156 return | |
157 action_data = data_format.deserialise(action_data_s) | |
158 if action_data.get("type") != C.META_TYPE_CALL: | |
159 return | |
160 peer_jid = jid.JID(action_data["from_jid"]).bare | |
161 caller = peer_jid.bare | |
162 if ( | |
163 not self.args.auto_accept_all | |
164 and caller not in self.args.auto_accept | |
165 and not await self.host.confirm( | |
166 _("📞 Incoming call from {caller}, do you accept?").format( | |
167 caller=caller | |
168 ) | |
169 ) | |
170 ): | |
171 await self.host.bridge.action_launch( | |
172 action_id, data_format.serialise({"cancelled": True}), profile | |
173 ) | |
174 return | |
175 | |
176 self.disp(_("✅ Incoming call from {caller} accepted.").format(caller=caller)) | |
177 | |
4206 | 178 await super().output(CallData( |
179 callee=peer_jid, | |
180 sid=action_data["session_id"], | |
181 action_id=action_id | |
182 )) | |
4143 | 183 |
184 async def start(self): | |
185 await super().start() | |
186 self.host.bridge.register_signal("action_new", self.on_action_new, "core") | |
187 | |
188 | |
189 class Call(base.CommandBase): | |
190 subcommands = (Make, Receive) | |
191 | |
192 def __init__(self, host): | |
193 super().__init__(host, "call", use_profile=False, help=_("A/V calls and related")) |