// SPDX-FileCopyrightText: 2020 Linus Jahn // // 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: template struct Items { QVector items; std::optional continuation; }; using Result = std::variant; using NodesResult = std::variant, QXmppStanza::Error>; using InstantNodeResult = std::variant; template using ItemResult = std::variant; template using ItemsResult = 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 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); template QFuture> requestItem(const QString &jid, const QString &nodeName, const QString &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 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); // PEP-specific (the PubSub service is the current account) 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 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 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); } /// \cond QStringList discoveryFeatures() const override; bool handleStanza(const QDomElement &element) override; /// \endcond private: /// \cond QFuture publishItem(QXmppPubSubIqBase &&iq); QFuture publishItems(QXmppPubSubIqBase &&iq); static QXmppPubSubIq<> requestItemsIq(const QString &jid, const QString &nodeName, const QStringList &itemIds); /// \endcond // 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 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