From 294b1e91004c5ab9d43e129b32249d0e654bb741 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Tue, 29 Oct 2019 12:09:54 +0100 Subject: [PATCH] Implement RsGxsForums link import/export --- libretroshare/src/retroshare/rsgxsforums.h | 56 +++++++++++++++ libretroshare/src/services/p3gxsforums.cc | 79 ++++++++++++++++++++++ libretroshare/src/services/p3gxsforums.h | 15 ++++ 3 files changed, 150 insertions(+) diff --git a/libretroshare/src/retroshare/rsgxsforums.h b/libretroshare/src/retroshare/rsgxsforums.h index 3be38691d..92f2d11d5 100644 --- a/libretroshare/src/retroshare/rsgxsforums.h +++ b/libretroshare/src/retroshare/rsgxsforums.h @@ -241,6 +241,62 @@ public: virtual bool subscribeToForum( const RsGxsGroupId& forumId, bool subscribe ) = 0; + /// default base URL used for forums links @see exportForumLink + static const std::string DEFAULT_FORUM_BASE_URL; + + /// Link query field used to store forum name @see exportForumLink + static const std::string FORUM_URL_NAME_FIELD; + + /// Link query field used to store forum id @see exportForumLink + static const std::string FORUM_URL_ID_FIELD; + + /// Link query field used to store forum data @see exportForumLink + static const std::string FORUM_URL_DATA_FIELD; + + /** Link query field used to store forum message title + * @see exportChannelLink */ + static const std::string FORUM_URL_MSG_TITLE_FIELD; + + /// Link query field used to store forum message id @see exportChannelLink + static const std::string FORUM_URL_MSG_ID_FIELD; + + /** + * @brief Get link to a forum + * @jsonapi{development} + * @param[out] link storage for the generated link + * @param[in] forumId Id of the forum of which we want to generate a link + * @param[in] includeGxsData if true include the forum GXS group data so + * the receiver can subscribe to the forum even if she hasn't received it + * through GXS yet + * @param[in] baseUrl URL into which to sneak in the RetroShare link + * radix, this is primarly useful to induce applications into making the + * link clickable, or to disguise the RetroShare link into a + * "normal" looking web link. If empty the GXS data link will be outputted + * in plain base64 format. + * @param[out] errMsg optional storage for error message, meaningful only in + * case of failure + * @return false if something failed, true otherwhise + */ + virtual bool exportForumLink( + std::string& link, const RsGxsGroupId& forumId, + bool includeGxsData = true, + const std::string& baseUrl = RsGxsForums::DEFAULT_FORUM_BASE_URL, + std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; + + /** + * @brief Import forum from full link + * @param[in] link forum link either in radix or URL format + * @param[out] forumId optional storage for parsed forum id + * @param[out] errMsg optional storage for error message, meaningful only in + * case of failure + * @return false if some error occurred, true otherwise + */ + virtual bool importForumLink( + const std::string& link, + RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), + std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; + + /** * @brief Create forum. Blocking API. * @jsonapi{development} diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc index 787ea22e1..775f0ddd3 100644 --- a/libretroshare/src/services/p3gxsforums.cc +++ b/libretroshare/src/services/p3gxsforums.cc @@ -676,6 +676,72 @@ bool p3GxsForums::subscribeToForum( return true; } +bool p3GxsForums::exportForumLink( + std::string& link, const RsGxsGroupId& forumId, bool includeGxsData, + const std::string& baseUrl, std::string& errMsg ) +{ + constexpr auto fname = __PRETTY_FUNCTION__; + const auto failure = [&](const std::string& err) + { + errMsg = err; + RsErr() << fname << " " << err << std::endl; + return false; + }; + + if(forumId.isNull()) return failure("forumId cannot be null"); + + const bool outputRadix = baseUrl.empty(); + if(outputRadix && !includeGxsData) return + failure("includeGxsData must be true if format requested is base64"); + + if( includeGxsData && + !RsGenExchange::exportGroupBase64(link, forumId, errMsg) ) + return failure(errMsg); + + if(outputRadix) return true; + + std::vector forumsInfo; + if( !getForumsInfo(std::list({forumId}), forumsInfo) + || forumsInfo.empty() ) + return failure("failure retrieving forum information"); + + RsUrl inviteUrl(baseUrl); + inviteUrl.setQueryKV(FORUM_URL_ID_FIELD, forumId.toStdString()); + inviteUrl.setQueryKV(FORUM_URL_NAME_FIELD, forumsInfo[0].mMeta.mGroupName); + if(includeGxsData) inviteUrl.setQueryKV(FORUM_URL_DATA_FIELD, link); + + link = inviteUrl.toString(); + return true; +} + +bool p3GxsForums::importForumLink( + const std::string& link, RsGxsGroupId& forumId, std::string& errMsg ) +{ + constexpr auto fname = __PRETTY_FUNCTION__; + const auto failure = [&](const std::string& err) + { + errMsg = err; + RsErr() << fname << " " << err << std::endl; + return false; + }; + + if(link.empty()) return failure("link is empty"); + + const std::string* radixPtr(&link); + + RsUrl url(link); + const auto& query = url.query(); + const auto qIt = query.find(FORUM_URL_DATA_FIELD); + if(qIt != query.end()) radixPtr = &qIt->second; + + if(radixPtr->empty()) return failure(FORUM_URL_DATA_FIELD + " is empty"); + + if(!RsGenExchange::importGroupBase64(*radixPtr, forumId, errMsg)) + return failure(errMsg); + + return true; +} + bool p3GxsForums::createGroup(uint32_t &token, RsGxsForumGroup &group) { std::cerr << "p3GxsForums::createGroup()" << std::endl; @@ -1005,6 +1071,19 @@ bool RsGxsForumGroup::canEditPosts(const RsGxsId& id) const id == mMeta.mAuthorId; } +/*static*/ const std::string RsGxsForums::DEFAULT_FORUM_BASE_URL = + "retroshare:///forums"; +/*static*/ const std::string RsGxsForums::FORUM_URL_NAME_FIELD = + "forumName"; +/*static*/ const std::string RsGxsForums::FORUM_URL_ID_FIELD = + "forumId"; +/*static*/ const std::string RsGxsForums::FORUM_URL_DATA_FIELD = + "forumData"; +/*static*/ const std::string RsGxsForums::FORUM_URL_MSG_TITLE_FIELD = + "forumMsgTitle"; +/*static*/ const std::string RsGxsForums::FORUM_URL_MSG_ID_FIELD = + "forumMsgId"; + RsGxsForumGroup::~RsGxsForumGroup() = default; RsGxsForumMsg::~RsGxsForumMsg() = default; RsGxsForums::~RsGxsForums() = default; diff --git a/libretroshare/src/services/p3gxsforums.h b/libretroshare/src/services/p3gxsforums.h index 910daff8d..8d2ea3294 100644 --- a/libretroshare/src/services/p3gxsforums.h +++ b/libretroshare/src/services/p3gxsforums.h @@ -110,6 +110,21 @@ public: virtual bool subscribeToForum( const RsGxsGroupId& forumId, bool subscribe ); + /// @see RsGxsForums + bool exportForumLink( + std::string& link, const RsGxsGroupId& forumId, + bool includeGxsData = true, + const std::string& baseUrl = DEFAULT_FORUM_BASE_URL, + std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) + ) override; + + /// @see RsGxsForums + bool importForumLink( + const std::string& link, + RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), + std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) + ) override; + virtual bool getGroupData(const uint32_t &token, std::vector &groups); virtual bool getMsgData(const uint32_t &token, std::vector &msgs); virtual bool getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas);