// SPDX-FileCopyrightText: 2020 Linus Jahn // SPDX-FileCopyrightText: 2022 Melvin Keskin // // SPDX-License-Identifier: LGPL-2.1-or-later #ifndef QXMPPPUBSUBMANAGER_H #define QXMPPPUBSUBMANAGER_H #include "QXmppClient.h" #include "QXmppClientExtension.h" #include "QXmppFutureUtils_p.h" #include "QXmppMessage.h" #include "QXmppPubSubIq.h" #include "QXmppPubSubPublishOptions.h" #include "QXmppResultSet.h" #include #include class QXmppPubSubPublishOptions; class QXmppPubSubSubscribeOptions; class QXMPP_EXPORT QXmppPubSubManager : public QXmppClientExtension { Q_OBJECT public: /// /// Type of PubSub service /// enum ServiceType { PubSubOrPep, ///< PubSub service or PEP service PubSub, ///< PubSub service only Pep ///< PEP service only }; /// /// Pre-defined ID of a PubSub item /// enum StandardItemId { Current ///< Item of a singleton node (i.e., the node's single item) }; /// /// Used to indicate a service type mismatch. /// struct InvalidServiceType { }; template struct Items { QVector items; std::optional continuation; }; using Result = std::variant; using FeaturesResult = std::variant, InvalidServiceType, QXmppStanza::Error>; using NodesResult = std::variant, QXmppStanza::Error>; using InstantNodeResult = std::variant; template using ItemResult = std::variant; template using ItemsResult = std::variant, QXmppStanza::Error>; using ItemIdsResult = std::variant, QXmppStanza::Error>; using PublishItemResult = std::variant; using PublishItemsResult = std::variant, QXmppStanza::Error>; using SubscriptionsResult = std::variant, QXmppStanza::Error>; using AffiliationsResult = std::variant, QXmppStanza::Error>; using OptionsResult = std::variant; using NodeConfigResult = std::variant; QXmppPubSubManager(); ~QXmppPubSubManager(); // Generic PubSub (the PubSub service is the given entity) QFuture requestFeatures(const QString &serviceJid, ServiceType serviceType = PubSubOrPep); QFuture fetchNodes(const QString &jid); QFuture createNode(const QString &jid, const QString &nodeName); QFuture createNode(const QString &jid, const QString &nodeName, const QXmppPubSubNodeConfig &config); QFuture createInstantNode(const QString &jid); QFuture createInstantNode(const QString &jid, const QXmppPubSubNodeConfig &config); QFuture deleteNode(const QString &jid, const QString &nodeName); QFuture requestItemIds(const QString &serviceJid, const QString &nodeName); template QFuture> requestItem(const QString &jid, const QString &nodeName, const QString &itemId); template QFuture> requestItem(const QString &jid, const QString &nodeName, StandardItemId itemId); template QFuture> requestItems(const QString &jid, const QString &nodeName); template QFuture> requestItems(const QString &jid, const QString &nodeName, const QStringList &itemIds); template QFuture publishItem(const QString &jid, const QString &nodeName, const T &item); template QFuture publishItem(const QString &jid, const QString &nodeName, const T &item, const QXmppPubSubPublishOptions &publishOptions); template QFuture publishItems(const QString &jid, const QString &nodeName, const QVector &items); template QFuture publishItems(const QString &jid, const QString &nodeName, const QVector &items, const QXmppPubSubPublishOptions &publishOptions); QFuture retractItem(const QString &jid, const QString &nodeName, const QString &itemId); QFuture retractItem(const QString &jid, const QString &nodeName, StandardItemId itemId); QFuture purgeItems(const QString &jid, const QString &nodeName); QFuture requestSubscriptions(const QString &jid); QFuture requestSubscriptions(const QString &jid, const QString &nodeName); QFuture requestNodeAffiliations(const QString &jid, const QString &nodeName); QFuture requestAffiliations(const QString &jid); QFuture requestAffiliations(const QString &jid, const QString &nodeName); QFuture requestSubscribeOptions(const QString &service, const QString &nodeName); QFuture requestSubscribeOptions(const QString &service, const QString &nodeName, const QString &subscriberJid); QFuture setSubscribeOptions(const QString &service, const QString &nodeName, const QXmppPubSubSubscribeOptions &options); QFuture setSubscribeOptions(const QString &service, const QString &nodeName, const QXmppPubSubSubscribeOptions &options, const QString &subscriberJid); QFuture requestNodeConfiguration(const QString &service, const QString &nodeName); QFuture configureNode(const QString &service, const QString &nodeName, const QXmppPubSubNodeConfig &config); QFuture cancelNodeConfiguration(const QString &service, const QString &nodeName); QFuture subscribeToNode(const QString &serviceJid, const QString &nodeName, const QString &subscriberJid); QFuture unsubscribeFromNode(const QString &serviceJid, const QString &nodeName, const QString &subscriberJid); // PEP-specific (the PubSub service is the current account) inline QFuture requestPepFeatures() { return requestFeatures(client()->configuration().jidBare(), Pep); }; inline QFuture fetchPepNodes() { return fetchNodes(client()->configuration().jidBare()); }; inline QFuture createPepNode(const QString &nodeName) { return createNode(client()->configuration().jidBare(), nodeName); } inline QFuture createPepNode(const QString &nodeName, const QXmppPubSubNodeConfig &config) { return createNode(client()->configuration().jidBare(), nodeName, config); } inline QFuture deletePepNode(const QString &nodeName) { return deleteNode(client()->configuration().jidBare(), nodeName); } template inline QFuture> requestPepItem(const QString &nodeName, const QString &itemId) { return requestItem(client()->configuration().jidBare(), nodeName, itemId); } template inline QFuture> requestPepItem(const QString &nodeName, StandardItemId itemId) { return requestItem(client()->configuration().jidBare(), nodeName, itemId); } template inline QFuture> requestPepItems(const QString &nodeName) { return requestItems(client()->configuration().jidBare(), nodeName); } inline QFuture requestPepItemIds(const QString &nodeName) { return requestItemIds(client()->configuration().jidBare(), nodeName); } template QFuture publishPepItem(const QString &nodeName, const T &item, const QXmppPubSubPublishOptions &publishOptions); template QFuture publishPepItem(const QString &nodeName, const T &item); template QFuture publishPepItems(const QString &nodeName, const QVector &items, const QXmppPubSubPublishOptions &publishOptions); template QFuture publishPepItems(const QString &nodeName, const QVector &items); inline QFuture retractPepItem(const QString &nodeName, const QString &itemId) { return retractItem(client()->configuration().jidBare(), nodeName, itemId); } inline QFuture retractPepItem(const QString &nodeName, StandardItemId itemId) { return retractItem(client()->configuration().jidBare(), nodeName, itemId); } inline QFuture purgePepItems(const QString &nodeName) { return purgeItems(client()->configuration().jidBare(), nodeName); } inline QFuture requestPepNodeConfiguration(const QString &nodeName) { return requestNodeConfiguration(client()->configuration().jidBare(), nodeName); } inline QFuture configurePepNode(const QString &nodeName, const QXmppPubSubNodeConfig &config) { return configureNode(client()->configuration().jidBare(), nodeName, config); } inline QFuture cancelPepNodeConfiguration(const QString &nodeName) { return cancelNodeConfiguration(client()->configuration().jidBare(), nodeName); } static QString standardItemIdToString(StandardItemId itemId); /// \cond QStringList discoveryFeatures() const override; bool handleStanza(const QDomElement &element) override; /// \endcond private: QFuture publishItem(QXmppPubSubIqBase &&iq); QFuture publishItems(QXmppPubSubIqBase &&iq); static QXmppPubSubIq<> requestItemsIq(const QString &jid, const QString &nodeName, const QStringList &itemIds); // We may need a d-ptr in the future. void *d = nullptr; }; /// /// Requests a specific item of an entity's node. /// /// \param jid Jabber ID of the entity hosting the pubsub service. For PEP this /// should be an account's bare JID /// \param nodeName the name of the node to query /// \param itemId the ID of the item to retrieve /// \return /// template QFuture> QXmppPubSubManager::requestItem(const QString &jid, const QString &nodeName, const QString &itemId) { using namespace QXmpp::Private; using Error = QXmppStanza::Error; return chainIq(client()->sendIq(requestItemsIq(jid, nodeName, { itemId })), this, [](QXmppPubSubIq &&iq) -> ItemResult { if (!iq.items().isEmpty()) { return iq.items().constFirst(); } return Error(Error::Cancel, Error::ItemNotFound, QStringLiteral("No such item has been found.")); }); } /// /// Requests a specific item of an entity's node. /// /// \param jid Jabber ID of the entity hosting the pubsub service. For PEP this /// should be an account's bare JID /// \param nodeName the name of the node to query /// \param itemId the ID of the item to retrieve /// \return /// template QFuture> QXmppPubSubManager::requestItem(const QString &jid, const QString &nodeName, StandardItemId itemId) { return requestItem(jid, nodeName, standardItemIdToString(itemId)); } /// /// Requests all items of an entity's node. /// /// \param jid Jabber ID of the entity hosting the pubsub service. For PEP this /// should be an account's bare JID /// \param nodeName the name of the node to query /// \return /// template QFuture> QXmppPubSubManager::requestItems(const QString &jid, const QString &nodeName) { return requestItems(jid, nodeName, {}); } /// /// Requests items of an entity's node. /// /// \param jid Jabber ID of the entity hosting the pubsub service. For PEP this /// should be an account's bare JID /// \param nodeName the name of the node to query /// \param itemIds the IDs of the items to retrieve. If empty, retrieves all /// items /// \return /// template QFuture> QXmppPubSubManager::requestItems(const QString &jid, const QString &nodeName, const QStringList &itemIds) { using namespace QXmpp::Private; return chainIq(client()->sendIq(requestItemsIq(jid, nodeName, itemIds)), this, [](QXmppPubSubIq &&iq) -> ItemsResult { return Items { iq.items(), iq.itemsContinuation(), }; }); } /// /// Publishs one item to a pubsub node. /// /// This is a convenience method equivalent to calling /// QXmppPubSubManager::publishItem with no publish options. /// /// \param jid Jabber ID of the entity hosting the pubsub service /// \param nodeName the name of the node to publish the item to /// \param item the item to publish /// \return /// template QFuture QXmppPubSubManager::publishItem(const QString &jid, const QString &nodeName, const T &item) { QXmppPubSubIq request; request.setTo(jid); request.setItems({ item }); request.setQueryNode(nodeName); return publishItem(std::move(request)); } /// /// Publishs one item to a pubsub node. /// /// This is a convenience method equivalent to calling /// QXmppPubSubManager::publishItem with no publish options. /// /// \param jid Jabber ID of the entity hosting the pubsub service /// \param nodeName the name of the node to publish the item to /// \param item the item to publish /// \param publishOptions publish-options for the items /// \return /// template QFuture QXmppPubSubManager::publishItem(const QString &jid, const QString &nodeName, const T &item, const QXmppPubSubPublishOptions &publishOptions) { QXmppPubSubIq request; request.setTo(jid); request.setItems({ item }); request.setQueryNode(nodeName); request.setDataForm(publishOptions.toDataForm()); return publishItem(std::move(request)); } /// /// Publishs items to a pubsub node. /// /// \param jid Jabber ID of the entity hosting the pubsub service /// \param nodeName the name of the node to publish the items to /// \param items the items to publish /// \return /// template QFuture QXmppPubSubManager::publishItems(const QString &jid, const QString &nodeName, const QVector &items) { QXmppPubSubIq request; request.setTo(jid); request.setItems(items); request.setQueryNode(nodeName); return publishItems(std::move(request)); } /// /// Publishs items to a pubsub node. /// /// \param jid Jabber ID of the entity hosting the pubsub service /// \param nodeName the name of the node to publish the items to /// \param items the items to publish /// \param publishOptions publish-options for the items /// \return /// template QFuture QXmppPubSubManager::publishItems(const QString &jid, const QString &nodeName, const QVector &items, const QXmppPubSubPublishOptions &publishOptions) { QXmppPubSubIq request; request.setTo(jid); request.setItems(items); request.setQueryNode(nodeName); request.setDataForm(publishOptions.toDataForm()); return publishItems(std::move(request)); } /// /// Publishs one item to a PEP node. /// /// \param nodeName the name of the PEP node to publish the item to /// \param item the item to publish /// \param publishOptions publish-options for fine tuning /// \return /// template QFuture QXmppPubSubManager::publishPepItem(const QString &nodeName, const T &item, const QXmppPubSubPublishOptions &publishOptions) { return publishItem(client()->configuration().jidBare(), nodeName, item, publishOptions); } /// /// Publishs one item to a PEP node. /// /// \param nodeName the name of the PEP node to publish the item to /// \param item the item to publish /// \return /// template QFuture QXmppPubSubManager::publishPepItem(const QString &nodeName, const T &item) { return publishItem(client()->configuration().jidBare(), nodeName, item); } /// /// Publishs items to a PEP node. /// /// \param nodeName the name of the PEP node to publish the items to /// \param items the items to publish /// \param publishOptions publish-options for fine tuning (optional). Pass /// an empty form to honor the default options of the PEP node /// \return /// template QFuture QXmppPubSubManager::publishPepItems(const QString &nodeName, const QVector &items, const QXmppPubSubPublishOptions &publishOptions) { return publishItems(client()->configuration().jidBare(), nodeName, items, publishOptions); } /// /// Publishs items to a PEP node. /// /// \param nodeName the name of the PEP node to publish the items to /// \param items the items to publish /// \return /// template QFuture QXmppPubSubManager::publishPepItems(const QString &nodeName, const QVector &items) { return publishItems(client()->configuration().jidBare(), nodeName, items); } #endif // QXMPPPUBSUBMANAGER_H