1// Copyright (c) 2023 xmpp-rs contributors.
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use tokio_xmpp::{
8 parsers::{
9 bookmarks,
10 disco::{DiscoInfoResult, Feature},
11 iq::Iq,
12 ns,
13 private::Query as PrivateXMLQuery,
14 pubsub::pubsub::{Items, PubSub},
15 Error as ParsersError,
16 },
17 Element, Jid,
18};
19
20use crate::Agent;
21
22// This method is a workaround due to prosody bug https://issues.prosody.im/1664
23// FIXME: To be removed in the future
24// The server doesn't return disco#info feature when querying the account
25// so we add it manually because we know it's true
26pub async fn handle_disco_info_result_payload(agent: &mut Agent, payload: Element, from: Jid) {
27 match DiscoInfoResult::try_from(payload.clone()) {
28 Ok(disco) => {
29 handle_disco_info_result(agent, disco, from).await;
30 }
31 Err(e) => match e {
32 ParsersError::ParseError(reason) => {
33 if reason == "disco#info feature not present in disco#info." {
34 let mut payload = payload.clone();
35 let disco_feature =
36 Feature::new("http://jabber.org/protocol/disco#info").into();
37 payload.append_child(disco_feature);
38 match DiscoInfoResult::try_from(payload) {
39 Ok(disco) => {
40 handle_disco_info_result(agent, disco, from).await;
41 }
42 Err(e) => {
43 panic!("Wrong disco#info format after workaround: {}", e)
44 }
45 }
46 } else {
47 panic!(
48 "Wrong disco#info format (reason cannot be worked around): {}",
49 e
50 )
51 }
52 }
53 _ => panic!("Wrong disco#info format: {}", e),
54 },
55 }
56}
57
58pub async fn handle_disco_info_result(agent: &mut Agent, disco: DiscoInfoResult, from: Jid) {
59 // Safe unwrap because no DISCO is received when we are not online
60 if from == agent.client.bound_jid().unwrap().to_bare() && agent.awaiting_disco_bookmarks_type {
61 info!("Received disco info about bookmarks type");
62 // Trigger bookmarks query
63 // TODO: only send this when the JoinRooms feature is enabled.
64 agent.awaiting_disco_bookmarks_type = false;
65 let mut perform_bookmarks2 = false;
66 info!("{:#?}", disco.features);
67 for feature in disco.features {
68 if feature.var == "urn:xmpp:bookmarks:1#compat" {
69 perform_bookmarks2 = true;
70 }
71 }
72
73 if perform_bookmarks2 {
74 // XEP-0402 bookmarks (modern)
75 let iq = Iq::from_get("bookmarks", PubSub::Items(Items::new(ns::BOOKMARKS2))).into();
76 let _ = agent.client.send_stanza(iq).await;
77 } else {
78 // XEP-0048 v1.0 bookmarks (legacy)
79 let iq = Iq::from_get(
80 "bookmarks-legacy",
81 PrivateXMLQuery {
82 storage: bookmarks::Storage::new(),
83 },
84 )
85 .into();
86 let _ = agent.client.send_stanza(iq).await;
87 }
88 } else {
89 unimplemented!("Ignored disco#info response from {}", from);
90 }
91}