2018-05-29 21:54:27 +02:00
/*******************************************************************************
* libretroshare / src / services : p3gxschannels . cc *
* *
* libretroshare : retroshare core library *
* *
2018-10-10 06:40:56 +02:00
* Copyright ( C ) 2012 Robert Fernie < retroshare @ lunamutt . com > *
2019-04-05 01:43:23 +02:00
* Copyright ( C ) 2018 - 2019 Gioacchino Mazzurco < gio @ eigenlab . org > *
2018-05-29 21:54:27 +02:00
* *
* This program is free software : you can redistribute it and / or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation , either version 3 of the *
* License , or ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU Lesser General Public License for more details . *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program . If not , see < https : //www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-03-04 20:26:48 +00:00
# include "services/p3gxschannels.h"
2017-04-26 20:57:28 +02:00
# include "rsitems/rsgxschannelitems.h"
2015-07-07 00:52:52 +00:00
# include "util/radix64.h"
# include "util/rsmemory.h"
2013-03-04 20:26:48 +00:00
# include <retroshare/rsidentity.h>
2013-03-13 00:24:57 +00:00
# include <retroshare/rsfiles.h>
2013-03-04 20:26:48 +00:00
# include "retroshare/rsgxsflags.h"
2013-03-16 12:31:31 +00:00
# include "retroshare/rsfiles.h"
2019-03-30 22:53:14 +01:00
# include "retroshare/rspeers.h"
2013-03-16 12:31:31 +00:00
2014-11-13 22:03:12 +00:00
# include "rsserver/p3face.h"
# include "retroshare/rsnotify.h"
2018-10-04 23:36:01 +02:00
# include <cstdio>
2018-11-17 17:19:13 +01:00
# include <chrono>
2019-04-05 01:43:23 +02:00
# include <string>
2013-03-04 20:26:48 +00:00
// For Dummy Msgs.
# include "util/rsrandom.h"
# include "util/rsstring.h"
2019-06-20 17:24:18 +02:00
# ifdef RS_DEEP_CHANNEL_INDEX
# include "deep_search / channelsindex.hpp"
# endif // RS_DEEP_CHANNEL_INDEX
2018-10-04 23:36:01 +02:00
2013-03-04 20:26:48 +00:00
/****
* # define GXSCHANNEL_DEBUG 1
* * * */
2018-11-17 17:19:13 +01:00
/*extern*/ RsGxsChannels * rsGxsChannels = nullptr ;
2013-03-04 20:26:48 +00:00
2013-03-13 00:24:57 +00:00
# define GXSCHANNEL_STOREPERIOD (3600 * 24 * 30)
2013-03-11 20:40:28 +00:00
# define GXSCHANNELS_SUBSCRIBED_META 1
# define GXSCHANNELS_UNPROCESSED_SPECIFIC 2
# define GXSCHANNELS_UNPROCESSED_GENERIC 3
# define CHANNEL_PROCESS 0x0001
# define CHANNEL_TESTEVENT_DUMMYDATA 0x0002
2020-11-22 21:45:21 +01:00
# define DUMMYDATA_PERIOD 60 // Long enough for some RsIdentities to be generated.
# define CHANNEL_DOWNLOAD_PERIOD (3600 * 24 * 7)
# define CHANNEL_MAX_AUTO_DL (8 * 1024 * 1024 * 1024ull) // 8 GB. Just a security ;-)
# define CHANNEL_UNUSED_BY_FRIENDS_DELAY (3600*24*60) // Two months. Will be used to delete a channel if too old
# define CHANNEL_DELAY_FOR_CHECKING_AND_DELETING_OLD_GROUPS 300 // check for old channels every 30 mins. Far too often than above delay by RS needs to run it at least once per session
2013-03-04 20:26:48 +00:00
/********************************************************************************/
/******************* Startup / Tick ******************************************/
/********************************************************************************/
2018-06-25 10:44:39 +02:00
p3GxsChannels : : p3GxsChannels (
RsGeneralDataService * gds , RsNetworkExchangeService * nes ,
RsGixs * gixs ) :
RsGenExchange ( gds , nes , new RsGxsChannelSerialiser ( ) ,
RS_SERVICE_GXS_TYPE_CHANNELS , gixs , channelsAuthenPolicy ( ) ) ,
2018-08-16 23:34:29 +02:00
RsGxsChannels ( static_cast < RsGxsIface & > ( * this ) ) , GxsTokenQueue ( this ) ,
2018-10-29 05:50:11 +01:00
mSubscribedGroupsMutex ( " GXS channels subscribed groups cache " ) ,
2020-06-16 21:13:55 +02:00
mKnownChannelsMutex ( " GXS channels known channels timestamp cache " )
# ifdef TO_REMOVE
2018-11-01 07:04:01 +01:00
mSearchCallbacksMapMutex ( " GXS channels search callbacks map " ) ,
mDistantChannelsCallbacksMapMutex ( " GXS channels distant channels callbacks map " )
2020-06-16 21:13:55 +02:00
# endif
2013-03-04 20:26:48 +00:00
{
// For Dummy Msgs.
mGenActive = false ;
2020-06-16 21:13:55 +02:00
mLastDistantSearchNotificationTS = 0 ;
2014-03-29 15:34:37 +00:00
mCommentService = new p3GxsCommentService ( this , RS_SERVICE_GXS_TYPE_CHANNELS ) ;
2013-03-04 20:26:48 +00:00
2021-01-19 19:38:38 +01:00
// This is not needed since it just loads all channel data ever 5 mins which takes a lot
// of useless CPU/memory.
//
// RsTickEvent::schedule_in(CHANNEL_PROCESS, 0);
//
2013-03-11 20:40:28 +00:00
// Test Data disabled in repo.
2021-01-19 19:38:38 +01:00
//
// RsTickEvent::schedule_in(CHANNEL_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD);
2015-06-18 15:20:51 +00:00
mGenToken = 0 ;
mGenCount = 0 ;
2013-03-04 20:26:48 +00:00
}
2014-03-22 03:53:44 +00:00
const std : : string GXS_CHANNELS_APP_NAME = " gxschannels " ;
const uint16_t GXS_CHANNELS_APP_MAJOR_VERSION = 1 ;
const uint16_t GXS_CHANNELS_APP_MINOR_VERSION = 0 ;
const uint16_t GXS_CHANNELS_MIN_MAJOR_VERSION = 1 ;
const uint16_t GXS_CHANNELS_MIN_MINOR_VERSION = 0 ;
RsServiceInfo p3GxsChannels : : getServiceInfo ( )
{
2014-03-29 15:34:37 +00:00
return RsServiceInfo ( RS_SERVICE_GXS_TYPE_CHANNELS ,
2014-03-22 03:53:44 +00:00
GXS_CHANNELS_APP_NAME ,
GXS_CHANNELS_APP_MAJOR_VERSION ,
GXS_CHANNELS_APP_MINOR_VERSION ,
GXS_CHANNELS_MIN_MAJOR_VERSION ,
GXS_CHANNELS_MIN_MINOR_VERSION ) ;
}
2013-03-04 20:26:48 +00:00
uint32_t p3GxsChannels : : channelsAuthenPolicy ( )
{
uint32_t policy = 0 ;
uint32_t flag = 0 ;
2013-03-10 15:08:04 +00:00
flag = GXS_SERV : : MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV : : MSG_AUTHEN_CHILD_AUTHOR_SIGN ;
2013-03-24 19:21:30 +00:00
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : PUBLIC_GRP_BITS ) ;
2013-03-04 20:26:48 +00:00
2013-03-10 15:08:04 +00:00
flag | = GXS_SERV : : MSG_AUTHEN_CHILD_PUBLISH_SIGN ;
2013-03-24 19:21:30 +00:00
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : RESTRICTED_GRP_BITS ) ;
2013-03-04 20:26:48 +00:00
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : PRIVATE_GRP_BITS ) ;
2013-03-24 19:21:30 +00:00
flag = 0 ;
RsGenExchange : : setAuthenPolicyFlag ( flag , policy , RsGenExchange : : GRP_OPTION_BITS ) ;
2013-03-04 20:26:48 +00:00
return policy ;
}
2018-02-16 23:51:43 +01:00
static const uint32_t GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400 * 30 * 2 ; // ignore notifications for 2 months
static const uint8_t GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ;
2020-03-04 19:17:09 +01:00
struct RsGxsChannelNotifyRecordsItem : public RsItem
2018-02-16 23:51:43 +01:00
{
2020-03-04 19:17:09 +01:00
RsGxsChannelNotifyRecordsItem ( )
2018-02-16 23:51:43 +01:00
: RsItem ( RS_PKT_VERSION_SERVICE , RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG , GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD )
{ }
2020-03-04 19:17:09 +01:00
virtual ~ RsGxsChannelNotifyRecordsItem ( ) { }
2018-02-16 23:51:43 +01:00
2018-04-27 20:55:38 +02:00
void serial_process ( RsGenericSerializer : : SerializeJob j ,
RsGenericSerializer : : SerializeContext & ctx )
{ RS_SERIAL_PROCESS ( records ) ; }
2018-02-16 23:51:43 +01:00
void clear ( ) { }
2018-10-07 01:34:05 +02:00
std : : map < RsGxsGroupId , rstime_t > records ;
2018-02-16 23:51:43 +01:00
} ;
class GxsChannelsConfigSerializer : public RsServiceSerializer
{
public :
2018-02-17 12:04:13 +01:00
GxsChannelsConfigSerializer ( ) : RsServiceSerializer ( RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG ) { }
2018-02-16 23:51:43 +01:00
virtual ~ GxsChannelsConfigSerializer ( ) { }
RsItem * create_item ( uint16_t service_id , uint8_t item_sub_id ) const
{
if ( service_id ! = RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG )
return NULL ;
switch ( item_sub_id )
{
2020-03-04 19:17:09 +01:00
case GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD : return new RsGxsChannelNotifyRecordsItem ( ) ;
2018-02-16 23:51:43 +01:00
default :
return NULL ;
}
}
} ;
bool p3GxsChannels : : saveList ( bool & cleanup , std : : list < RsItem * > & saveList )
{
cleanup = true ;
2020-03-04 19:17:09 +01:00
RsGxsChannelNotifyRecordsItem * item = new RsGxsChannelNotifyRecordsItem ;
2018-02-16 23:51:43 +01:00
2018-10-29 05:50:11 +01:00
{
RS_STACK_MUTEX ( mKnownChannelsMutex ) ;
item - > records = mKnownChannels ;
}
2018-02-16 23:51:43 +01:00
saveList . push_back ( item ) ;
return true ;
}
bool p3GxsChannels : : loadList ( std : : list < RsItem * > & loadList )
{
while ( ! loadList . empty ( ) )
{
RsItem * item = loadList . front ( ) ;
loadList . pop_front ( ) ;
2018-10-07 01:34:05 +02:00
rstime_t now = time ( NULL ) ;
2018-02-16 23:51:43 +01:00
2020-03-04 19:17:09 +01:00
RsGxsChannelNotifyRecordsItem * fnr = dynamic_cast < RsGxsChannelNotifyRecordsItem * > ( item ) ;
2018-02-16 23:51:43 +01:00
2018-10-29 05:50:11 +01:00
if ( fnr )
2018-02-16 23:51:43 +01:00
{
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mKnownChannelsMutex ) ;
2018-02-16 23:51:43 +01:00
mKnownChannels . clear ( ) ;
for ( auto it ( fnr - > records . begin ( ) ) ; it ! = fnr - > records . end ( ) ; + + it )
2020-11-22 21:45:21 +01:00
if ( now < it - > second + GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE )
2018-02-16 23:51:43 +01:00
mKnownChannels . insert ( * it ) ;
}
delete item ;
}
return true ;
}
RsSerialiser * p3GxsChannels : : setupSerialiser ( )
{
RsSerialiser * rss = new RsSerialiser ;
rss - > addSerialType ( new GxsChannelsConfigSerializer ( ) ) ;
return rss ;
}
2013-03-04 20:26:48 +00:00
2013-03-16 12:31:31 +00:00
/** Overloaded to cache new groups **/
2015-11-30 00:02:44 -05:00
RsGenExchange : : ServiceCreate_Return p3GxsChannels : : service_CreateGroup ( RsGxsGrpItem * grpItem , RsTlvSecurityKeySet & /* keySet */ )
2013-03-16 12:31:31 +00:00
{
updateSubscribedGroup ( grpItem - > meta ) ;
return SERVICE_CREATE_SUCCESS ;
}
2013-03-04 20:26:48 +00:00
void p3GxsChannels : : notifyChanges ( std : : vector < RsGxsNotify * > & changes )
{
2020-09-03 20:53:57 +02:00
# ifdef GXSCHANNEL_DEBUG
RsDbg ( ) < < " Processing " < < changes . size ( ) < < " channel changes... " < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2020-09-03 20:53:57 +02:00
/* iterate through and grab any new messages */
2020-05-03 23:20:13 +02:00
std : : set < RsGxsGroupId > unprocessedGroups ;
2013-03-11 20:40:28 +00:00
std : : vector < RsGxsNotify * > : : iterator it ;
2014-10-24 22:07:26 +00:00
for ( it = changes . begin ( ) ; it ! = changes . end ( ) ; + + it )
2013-03-11 20:40:28 +00:00
{
RsGxsMsgChange * msgChange = dynamic_cast < RsGxsMsgChange * > ( * it ) ;
2020-02-03 21:39:05 +01:00
2014-11-13 22:03:12 +00:00
if ( msgChange )
2013-03-11 20:40:28 +00:00
{
2020-01-11 17:00:01 +01:00
if ( msgChange - > getType ( ) = = RsGxsNotify : : TYPE_RECEIVED_NEW | | msgChange - > getType ( ) = = RsGxsNotify : : TYPE_PUBLISHED )
2014-11-13 22:03:12 +00:00
{
/* message received */
2019-12-13 23:40:21 +01:00
if ( rsEvents )
2014-11-13 22:03:12 +00:00
{
2020-05-03 23:20:13 +02:00
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelMsgId = msgChange - > mMsgId ;
ev - > mChannelGroupId = msgChange - > mGroupId ;
2020-11-07 16:55:15 +01:00
if ( nullptr ! = dynamic_cast < RsGxsCommentItem * > ( msgChange - > mNewMsgItem ) )
ev - > mChannelEventCode = RsChannelEventCode : : NEW_COMMENT ;
else
if ( nullptr ! = dynamic_cast < RsGxsVoteItem * > ( msgChange - > mNewMsgItem ) )
ev - > mChannelEventCode = RsChannelEventCode : : NEW_VOTE ;
else
ev - > mChannelEventCode = RsChannelEventCode : : NEW_MESSAGE ;
2020-05-03 23:20:13 +02:00
rsEvents - > postEvent ( ev ) ;
2014-11-13 22:03:12 +00:00
}
}
2013-03-11 20:40:28 +00:00
2014-11-13 22:03:12 +00:00
if ( ! msgChange - > metaChange ( ) )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2014-11-13 22:03:12 +00:00
std : : cerr < < " p3GxsChannels::notifyChanges() Found Message Change Notification " ;
2013-03-11 20:40:28 +00:00
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2020-05-03 23:20:13 +02:00
std : : cerr < < " p3GxsChannels::notifyChanges() Msgs for Group: " < < mit - > first ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2020-05-03 23:20:13 +02:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2020-05-03 23:20:13 +02:00
std : : cerr < < " p3GxsChannels::notifyChanges() AutoDownload for Group: " < < mit - > first ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2014-11-13 22:03:12 +00:00
2020-05-03 23:20:13 +02:00
/* problem is most of these will be comments and votes, should make it occasional - every 5mins / 10minutes TODO */
// We do not call if(autoDownLoadEnabled()) here, because it would be too costly when
// many msgs are received from the same group. We back the groupIds and then request one by one.
unprocessedGroups . insert ( msgChange - > mGroupId ) ;
2014-11-13 22:03:12 +00:00
}
}
}
2020-02-03 21:39:05 +01:00
RsGxsGroupChange * grpChange = dynamic_cast < RsGxsGroupChange * > ( * it ) ;
if ( grpChange & & rsEvents )
2014-11-13 22:03:12 +00:00
{
2020-09-03 20:53:57 +02:00
# ifdef GXSCHANNEL_DEBUG
RsDbg ( ) < < " Grp Change Event or type " < < grpChange - > getType ( ) < < " : " < < std : : endl ;
# endif
2020-02-03 21:39:05 +01:00
switch ( grpChange - > getType ( ) )
2014-11-13 22:03:12 +00:00
{
2020-02-03 21:39:05 +01:00
case RsGxsNotify : : TYPE_PROCESSED : // happens when the group is subscribed
{
2020-05-01 00:00:13 +02:00
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : SUBSCRIBE_STATUS_CHANGED ;
rsEvents - > postEvent ( ev ) ;
2020-02-03 21:39:05 +01:00
}
break ;
2019-12-16 22:44:37 +01:00
2020-10-24 21:17:34 +02:00
case RsGxsNotify : : TYPE_GROUP_SYNC_PARAMETERS_UPDATED :
{
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : SYNC_PARAMETERS_UPDATED ;
rsEvents - > postEvent ( ev ) ;
}
break ;
2020-04-11 20:52:35 +02:00
case RsGxsNotify : : TYPE_STATISTICS_CHANGED :
2020-05-01 00:00:13 +02:00
{
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : STATISTICS_CHANGED ;
rsEvents - > postEvent ( ev ) ;
2020-11-22 21:45:21 +01:00
// also update channel usage. Statistics are updated when a friend sends some sync packets
RS_STACK_MUTEX ( mKnownChannelsMutex ) ;
mKnownChannels [ grpChange - > mGroupId ] = time ( NULL ) ;
IndicateConfigChanged ( ) ;
}
2020-04-11 20:52:35 +02:00
break ;
2020-11-28 23:10:40 +01:00
case RsGxsNotify : : TYPE_UPDATED :
{
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : UPDATED_CHANNEL ;
rsEvents - > postEvent ( ev ) ;
}
break ;
case RsGxsNotify : : TYPE_PUBLISHED :
2020-02-03 21:39:05 +01:00
case RsGxsNotify : : TYPE_RECEIVED_NEW :
{
2020-11-22 21:45:21 +01:00
/* group received or updated */
2020-05-01 00:00:13 +02:00
2020-11-22 21:45:21 +01:00
bool unknown ;
{
RS_STACK_MUTEX ( mKnownChannelsMutex ) ;
unknown = ( mKnownChannels . find ( grpChange - > mGroupId ) = = mKnownChannels . end ( ) ) ;
mKnownChannels [ grpChange - > mGroupId ] = time ( NULL ) ;
IndicateConfigChanged ( ) ;
}
2020-05-01 00:00:13 +02:00
2020-09-03 20:53:57 +02:00
# ifdef GXSCHANNEL_DEBUG
RsDbg ( ) < < " Type = Published/New " < < std : : endl ;
# endif
2020-11-22 21:45:21 +01:00
if ( unknown )
2020-02-03 21:39:05 +01:00
{
2020-09-03 20:53:57 +02:00
# ifdef GXSCHANNEL_DEBUG
RsDbg ( ) < < " Status: unknown. Sending notification event. " < < std : : endl ;
# endif
2020-05-01 00:00:13 +02:00
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : NEW_CHANNEL ;
rsEvents - > postEvent ( ev ) ;
2020-09-03 20:53:57 +02:00
}
# ifdef GXSCHANNEL_DEBUG
2020-05-01 00:00:13 +02:00
else
2020-09-03 20:53:57 +02:00
RsDbg ( ) < < " Not notifying already known channel " < < grpChange - > mGroupId < < std : : endl ;
# endif
2020-02-03 21:39:05 +01:00
}
2020-05-01 00:00:13 +02:00
break ;
2020-02-03 21:39:05 +01:00
2020-11-25 23:35:20 +01:00
case RsGxsNotify : : TYPE_GROUP_DELETED :
{
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : DELETED_CHANNEL ;
rsEvents - > postEvent ( ev ) ;
}
break ;
case RsGxsNotify : : TYPE_RECEIVED_PUBLISHKEY :
2020-02-03 21:39:05 +01:00
{
/* group received */
2020-05-01 00:00:13 +02:00
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelGroupId = grpChange - > mGroupId ;
ev - > mChannelEventCode = RsChannelEventCode : : RECEIVED_PUBLISH_KEY ;
2020-02-03 21:39:05 +01:00
2020-05-01 00:00:13 +02:00
rsEvents - > postEvent ( ev ) ;
2020-02-03 21:39:05 +01:00
}
2020-04-11 20:52:35 +02:00
break ;
default :
RsErr ( ) < < " Got a GXS event of type " < < grpChange - > getType ( ) < < " Currently not handled. " < < std : : endl ;
break ;
2013-03-11 20:40:28 +00:00
}
2020-04-11 20:52:35 +02:00
2013-03-11 20:40:28 +00:00
}
2013-03-16 12:31:31 +00:00
/* shouldn't need to worry about groups - as they need to be subscribed to */
2020-01-27 21:38:57 +01:00
delete * it ;
2013-03-11 20:40:28 +00:00
}
2020-05-03 23:20:13 +02:00
std : : list < RsGxsGroupId > grps ;
for ( auto & grp_id : unprocessedGroups )
{
bool enabled = false ;
if ( autoDownloadEnabled ( grp_id , enabled ) & & enabled ) // costly call, that's why it's packed down here.
grps . push_back ( grp_id ) ;
}
if ( ! grps . empty ( ) )
request_SpecificSubscribedGroups ( grps ) ;
2013-03-04 20:26:48 +00:00
}
void p3GxsChannels : : service_tick ( )
{
2018-10-29 05:50:11 +01:00
static rstime_t last_dummy_tick = 0 ;
2020-06-16 21:13:55 +02:00
rstime_t now = time ( NULL ) ;
2013-03-16 12:31:31 +00:00
if ( time ( NULL ) > last_dummy_tick + 5 )
{
dummy_tick ( ) ;
2020-06-16 21:13:55 +02:00
last_dummy_tick = now ;
2013-03-16 12:31:31 +00:00
}
2013-03-04 20:26:48 +00:00
RsTickEvent : : tick_events ( ) ;
2013-03-15 20:46:49 +00:00
GxsTokenQueue : : checkRequests ( ) ;
mCommentService - > comment_tick ( ) ;
2020-06-16 21:13:55 +02:00
// Notify distant search results, not more than once per sec. Normally we should
// rather send one item for all, but that needs another class type
if ( now > mLastDistantSearchNotificationTS + 2 & & ! mSearchResultsToNotify . empty ( ) )
{
auto ev = std : : make_shared < RsGxsChannelSearchResultEvent > ( ) ;
ev - > mSearchResultsMap = mSearchResultsToNotify ;
mLastDistantSearchNotificationTS = now ;
mSearchResultsToNotify . clear ( ) ;
rsEvents - > postEvent ( ev ) ;
}
2013-03-04 20:26:48 +00:00
}
2020-11-22 21:45:21 +01:00
bool p3GxsChannels : : service_checkIfGroupIsStillUsed ( const RsGxsGrpMetaData & meta )
{
2020-11-26 20:03:03 +01:00
# ifdef GXSFORUMS_CHANNELS
2020-11-22 21:45:21 +01:00
std : : cerr < < " p3gxsChannels: Checking unused channel: called by GxsCleaning. " < < std : : endl ;
2020-11-26 20:03:03 +01:00
# endif
2020-11-22 21:45:21 +01:00
// request all group infos at once
rstime_t now = time ( nullptr ) ;
RS_STACK_MUTEX ( mKnownChannelsMutex ) ;
auto it = mKnownChannels . find ( meta . mGroupId ) ;
bool unknown_channel = it = = mKnownChannels . end ( ) ;
2020-11-26 20:03:03 +01:00
# ifdef GXSFORUMS_CHANNELS
2020-11-22 21:45:21 +01:00
std : : cerr < < " Channel " < < meta . mGroupId ;
2020-11-26 20:03:03 +01:00
# endif
2020-11-22 21:45:21 +01:00
if ( unknown_channel )
{
// This case should normally not happen. It does because this channel was never registered since it may
// arrived before this code was here
2020-11-26 20:03:03 +01:00
# ifdef GXSFORUMS_CHANNELS
2020-11-22 21:45:21 +01:00
std : : cerr < < " . Not known yet. Adding current time as new TS. " < < std : : endl ;
2020-11-26 20:03:03 +01:00
# endif
2020-11-22 21:45:21 +01:00
mKnownChannels [ meta . mGroupId ] = now ;
IndicateConfigChanged ( ) ;
return true ;
}
else
{
bool used_by_friends = ( now < it - > second + CHANNEL_UNUSED_BY_FRIENDS_DELAY ) ;
bool subscribed = static_cast < bool > ( meta . mSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED ) ;
2020-11-26 20:03:03 +01:00
# ifdef GXSFORUMS_CHANNELS
2020-11-22 21:45:21 +01:00
std : : cerr < < " . subscribed: " < < subscribed < < " , used_by_friends: " < < used_by_friends < < " last TS: " < < now - it - > second < < " secs ago ( " < < ( now - it - > second ) / 86400 < < " days) " ;
2020-11-26 20:03:03 +01:00
# endif
2020-11-22 21:45:21 +01:00
if ( ! subscribed & & ! used_by_friends )
{
2020-11-26 20:03:03 +01:00
# ifdef GXSFORUMS_CHANNELS
2020-11-22 21:45:21 +01:00
std : : cerr < < " . Scheduling for deletion " < < std : : endl ;
2020-11-26 20:03:03 +01:00
# endif
2020-11-22 21:45:21 +01:00
return false ;
}
else
{
2020-11-26 20:03:03 +01:00
# ifdef GXSFORUMS_CHANNELS
2020-11-22 21:45:21 +01:00
std : : cerr < < " . Keeping! " < < std : : endl ;
2020-11-26 20:03:03 +01:00
# endif
2020-11-22 21:45:21 +01:00
return true ;
}
}
}
2013-03-04 20:26:48 +00:00
bool p3GxsChannels : : getGroupData ( const uint32_t & token , std : : vector < RsGxsChannelGroup > & groups )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-11 20:40:28 +00:00
std : : cerr < < " p3GxsChannels::getGroupData() " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2013-03-04 20:26:48 +00:00
std : : vector < RsGxsGrpItem * > grpData ;
bool ok = RsGenExchange : : getGroupData ( token , grpData ) ;
2013-07-21 01:50:13 +00:00
2013-03-04 20:26:48 +00:00
if ( ok )
{
std : : vector < RsGxsGrpItem * > : : iterator vit = grpData . begin ( ) ;
2014-10-24 22:07:26 +00:00
for ( ; vit ! = grpData . end ( ) ; + + vit )
2013-03-04 20:26:48 +00:00
{
RsGxsChannelGroupItem * item = dynamic_cast < RsGxsChannelGroupItem * > ( * vit ) ;
2013-03-11 20:40:28 +00:00
if ( item )
{
RsGxsChannelGroup grp ;
item - > toChannelGroup ( grp , true ) ;
delete item ;
groups . push_back ( grp ) ;
}
else
{
std : : cerr < < " p3GxsChannels::getGroupData() ERROR in decode " ;
std : : cerr < < std : : endl ;
2013-07-21 01:50:13 +00:00
delete ( * vit ) ;
2013-03-11 20:40:28 +00:00
}
2013-03-04 20:26:48 +00:00
}
}
2013-03-11 20:40:28 +00:00
else
{
std : : cerr < < " p3GxsChannels::getGroupData() ERROR in request " ;
std : : cerr < < std : : endl ;
}
2013-03-04 20:26:48 +00:00
return ok ;
}
2018-06-26 13:20:24 +02:00
bool p3GxsChannels : : groupShareKeys (
const RsGxsGroupId & groupId , const std : : set < RsPeerId > & peers )
2014-10-05 19:14:05 +00:00
{
2018-06-26 13:20:24 +02:00
RsGenExchange : : shareGroupPublishKey ( groupId , peers ) ;
return true ;
2014-10-05 19:14:05 +00:00
}
2013-03-04 20:26:48 +00:00
/* Okay - chris is not going to be happy with this...
* but I can ' t be bothered with crazy data structures
* at the moment - fix it up later
*/
2020-11-08 14:57:17 +01:00
bool p3GxsChannels : : getPostData ( const uint32_t & token , std : : vector < RsGxsChannelPost > & msgs ,
std : : vector < RsGxsComment > & cmts ,
std : : vector < RsGxsVote > & vots )
2013-03-04 20:26:48 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2020-04-27 17:24:36 +02:00
RsDbg ( ) < < __PRETTY_FUNCTION__ < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2013-03-04 20:26:48 +00:00
GxsMsgDataMap msgData ;
2018-10-29 05:50:11 +01:00
if ( ! RsGenExchange : : getMsgData ( token , msgData ) )
{
2020-04-27 17:24:36 +02:00
RsErr ( ) < < __PRETTY_FUNCTION__ < < " ERROR in request " < < std : : endl ;
2018-10-29 05:50:11 +01:00
return false ;
}
2013-07-21 01:50:13 +00:00
2018-10-29 05:50:11 +01:00
GxsMsgDataMap : : iterator mit = msgData . begin ( ) ;
2020-04-27 17:24:36 +02:00
for ( ; mit ! = msgData . end ( ) ; + + mit )
2013-03-04 20:26:48 +00:00
{
2018-10-29 05:50:11 +01:00
std : : vector < RsGxsMsgItem * > & msgItems = mit - > second ;
std : : vector < RsGxsMsgItem * > : : iterator vit = msgItems . begin ( ) ;
for ( ; vit ! = msgItems . end ( ) ; + + vit )
2013-03-04 20:26:48 +00:00
{
2018-10-29 05:50:11 +01:00
RsGxsChannelPostItem * postItem =
dynamic_cast < RsGxsChannelPostItem * > ( * vit ) ;
2013-07-21 01:50:13 +00:00
2018-10-29 05:50:11 +01:00
if ( postItem )
2013-03-04 20:26:48 +00:00
{
2018-10-29 05:50:11 +01:00
RsGxsChannelPost msg ;
postItem - > toChannelPost ( msg , true ) ;
msgs . push_back ( msg ) ;
delete postItem ;
}
else
{
RsGxsCommentItem * cmtItem =
dynamic_cast < RsGxsCommentItem * > ( * vit ) ;
if ( cmtItem )
2013-03-04 20:26:48 +00:00
{
2018-10-29 05:50:11 +01:00
RsGxsComment cmt ;
RsGxsMsgItem * mi = ( * vit ) ;
cmt = cmtItem - > mMsg ;
cmt . mMeta = mi - > meta ;
# ifdef GXSCOMMENT_DEBUG
2020-04-27 17:24:36 +02:00
RsDbg ( ) < < __PRETTY_FUNCTION__ < < " Found Comment: " < < std : : endl ;
2018-10-29 05:50:11 +01:00
cmt . print ( std : : cerr , " " , " cmt " ) ;
# endif
cmts . push_back ( cmt ) ;
delete cmtItem ;
2013-03-04 20:26:48 +00:00
}
else
{
2020-04-27 17:24:36 +02:00
RsGxsVoteItem * votItem =
dynamic_cast < RsGxsVoteItem * > ( * vit ) ;
if ( votItem )
{
RsGxsVote vot ;
RsGxsMsgItem * mi = ( * vit ) ;
vot = votItem - > mMsg ;
vot . mMeta = mi - > meta ;
vots . push_back ( vot ) ;
delete votItem ;
}
else
{
RsGxsMsgItem * msg = ( * vit ) ;
//const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217;
//const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03;
//const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1;
//const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2;
RsErr ( ) < < __PRETTY_FUNCTION__
< < " Not a GxsChannelPostItem neither a "
< < " RsGxsCommentItem neither a RsGxsVoteItem "
< < " PacketService= " < < std : : hex < < ( int ) msg - > PacketService ( ) < < std : : dec
< < " PacketSubType= " < < std : : hex < < ( int ) msg - > PacketSubType ( ) < < std : : dec
< < " type name = " < < typeid ( * msg ) . name ( )
< < " , deleting! " < < std : : endl ;
delete * vit ;
}
2013-03-04 20:26:48 +00:00
}
}
}
}
2013-07-21 01:50:13 +00:00
2018-10-29 05:50:11 +01:00
return true ;
}
2020-04-27 17:24:36 +02:00
bool p3GxsChannels : : getPostData (
const uint32_t & token , std : : vector < RsGxsChannelPost > & posts , std : : vector < RsGxsComment > & cmts )
{
std : : vector < RsGxsVote > vots ;
return getPostData ( token , posts , cmts , vots ) ;
}
2018-10-29 05:50:11 +01:00
bool p3GxsChannels : : getPostData (
const uint32_t & token , std : : vector < RsGxsChannelPost > & posts )
{
std : : vector < RsGxsComment > cmts ;
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsVote > vots ;
return getPostData ( token , posts , cmts , vots ) ;
2013-03-04 20:26:48 +00:00
}
2016-06-18 20:03:55 +02:00
//Not currently used
/*bool p3GxsChannels::getRelatedPosts(const uint32_t &token, std::vector<RsGxsChannelPost> &msgs)
2013-03-04 20:26:48 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-11 20:40:28 +00:00
std : : cerr < < " p3GxsChannels::getRelatedPosts() " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2013-03-04 20:26:48 +00:00
GxsMsgRelatedDataMap msgData ;
bool ok = RsGenExchange : : getMsgRelatedData ( token , msgData ) ;
if ( ok )
{
GxsMsgRelatedDataMap : : iterator mit = msgData . begin ( ) ;
2014-10-24 22:07:26 +00:00
for ( ; mit ! = msgData . end ( ) ; + + mit )
2013-03-04 20:26:48 +00:00
{
std : : vector < RsGxsMsgItem * > & msgItems = mit - > second ;
std : : vector < RsGxsMsgItem * > : : iterator vit = msgItems . begin ( ) ;
2014-10-24 22:07:26 +00:00
for ( ; vit ! = msgItems . end ( ) ; + + vit )
2013-03-04 20:26:48 +00:00
{
RsGxsChannelPostItem * item = dynamic_cast < RsGxsChannelPostItem * > ( * vit ) ;
if ( item )
{
2013-03-11 20:40:28 +00:00
RsGxsChannelPost msg ;
item - > toChannelPost ( msg , true ) ;
2013-03-04 20:26:48 +00:00
msgs . push_back ( msg ) ;
delete item ;
}
else
{
2016-02-08 19:42:56 +01:00
RsGxsCommentItem * cmt = dynamic_cast < RsGxsCommentItem * > ( * vit ) ;
if ( ! cmt )
{
RsGxsMsgItem * msg = ( * vit ) ;
//const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217;
//const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03;
//const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1;
std : : cerr < < " Not a GxsChannelPostItem neither a RsGxsCommentItem "
< < " PacketService= " < < std : : hex < < ( int ) msg - > PacketService ( ) < < std : : dec
< < " PacketSubType= " < < std : : hex < < ( int ) msg - > PacketSubType ( ) < < std : : dec
< < " , deleting! " < < std : : endl ;
}
2013-03-04 20:26:48 +00:00
delete * vit ;
}
}
}
}
2013-03-11 20:40:28 +00:00
else
{
std : : cerr < < " p3GxsChannels::getRelatedPosts() ERROR in request " ;
std : : cerr < < std : : endl ;
}
2013-03-04 20:26:48 +00:00
return ok ;
2016-06-18 20:03:55 +02:00
} */
2013-03-04 20:26:48 +00:00
2013-03-11 20:40:28 +00:00
/********************************************************************************************/
/********************************************************************************************/
2013-03-16 12:31:31 +00:00
bool p3GxsChannels : : setChannelAutoDownload ( const RsGxsGroupId & groupId , bool enabled )
{
return setAutoDownload ( groupId , enabled ) ;
}
2015-07-07 00:52:52 +00:00
bool p3GxsChannels : : getChannelAutoDownload ( const RsGxsGroupId & groupId , bool & enabled )
2013-03-16 12:31:31 +00:00
{
2015-07-07 00:52:52 +00:00
return autoDownloadEnabled ( groupId , enabled ) ;
2013-03-16 12:31:31 +00:00
}
2018-11-01 07:04:01 +01:00
bool p3GxsChannels : : setChannelDownloadDirectory (
const RsGxsGroupId & groupId , const std : : string & directory )
2015-07-07 00:52:52 +00:00
{
# ifdef GXSCHANNELS_DEBUG
2018-11-01 07:04:01 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " id: " < < groupId < < " to: "
< < directory < < std : : endl ;
2015-07-07 00:52:52 +00:00
# endif
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mSubscribedGroupsMutex ) ;
2015-07-07 00:52:52 +00:00
2018-10-29 05:50:11 +01:00
std : : map < RsGxsGroupId , RsGroupMetaData > : : iterator it ;
2018-11-01 07:04:01 +01:00
it = mSubscribedGroups . find ( groupId ) ;
if ( it = = mSubscribedGroups . end ( ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Unknown groupId: "
< < groupId . toStdString ( ) < < std : : endl ;
return false ;
}
2015-07-07 00:52:52 +00:00
/* extract from ServiceString */
2020-11-06 23:08:18 +01:00
GxsChannelGroupInfo ss ;
2015-07-07 00:52:52 +00:00
ss . load ( it - > second . mServiceString ) ;
2018-11-01 07:04:01 +01:00
if ( directory = = ss . mDownloadDirectory )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Warning! groupId: " < < groupId
< < " Was already configured to download into: " < < directory
< < std : : endl ;
return false ;
}
2015-07-07 00:52:52 +00:00
ss . mDownloadDirectory = directory ;
std : : string serviceString = ss . save ( ) ;
uint32_t token ;
it - > second . mServiceString = serviceString ; // update Local Cache.
RsGenExchange : : setGroupServiceString ( token , groupId , serviceString ) ; // update dbase.
2018-11-01 07:04:01 +01:00
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Feiled setting group "
< < " service string " < < std : : endl ;
return false ;
}
2015-07-07 00:52:52 +00:00
/* now reload it */
std : : list < RsGxsGroupId > groups ;
groups . push_back ( groupId ) ;
2013-03-11 20:40:28 +00:00
2015-07-07 00:52:52 +00:00
request_SpecificSubscribedGroups ( groups ) ;
return true ;
}
2016-02-17 19:27:28 +01:00
bool p3GxsChannels : : getChannelDownloadDirectory ( const RsGxsGroupId & groupId , std : : string & directory )
2015-07-07 00:52:52 +00:00
{
# ifdef GXSCHANNELS_DEBUG
2016-02-17 19:27:28 +01:00
std : : cerr < < " p3GxsChannels::getChannelDownloadDirectory( " < < id < < " ) " < < std : : endl ;
2015-07-07 00:52:52 +00:00
# endif
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mSubscribedGroupsMutex ) ;
2015-07-07 00:52:52 +00:00
std : : map < RsGxsGroupId , RsGroupMetaData > : : iterator it ;
2018-11-01 07:04:01 +01:00
it = mSubscribedGroups . find ( groupId ) ;
if ( it = = mSubscribedGroups . end ( ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Unknown groupId: "
< < groupId . toStdString ( ) < < std : : endl ;
return false ;
}
2015-07-07 00:52:52 +00:00
/* extract from ServiceString */
2020-11-06 23:08:18 +01:00
GxsChannelGroupInfo ss ;
2015-07-07 00:52:52 +00:00
ss . load ( it - > second . mServiceString ) ;
directory = ss . mDownloadDirectory ;
2018-11-01 07:04:01 +01:00
return true ;
2015-07-07 00:52:52 +00:00
}
2013-03-11 20:40:28 +00:00
void p3GxsChannels : : request_AllSubscribedGroups ( )
{
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::request_SubscribedGroups() " ;
std : : cerr < < std : : endl ;
2013-03-11 20:40:28 +00:00
# endif // GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_META ;
2013-03-11 20:40:28 +00:00
2013-03-16 12:31:31 +00:00
uint32_t token = 0 ;
2013-03-11 20:40:28 +00:00
2013-03-16 12:31:31 +00:00
RsGenExchange : : getTokenService ( ) - > requestGroupInfo ( token , ansType , opts ) ;
GxsTokenQueue : : queueRequest ( token , GXSCHANNELS_SUBSCRIBED_META ) ;
2013-03-11 20:40:28 +00:00
2013-03-16 12:31:31 +00:00
# define PERIODIC_ALL_PROCESS 300 // TESTING every 5 minutes.
RsTickEvent : : schedule_in ( CHANNEL_PROCESS , PERIODIC_ALL_PROCESS ) ;
2013-03-11 20:40:28 +00:00
}
2020-05-03 23:20:13 +02:00
void p3GxsChannels : : request_SpecificSubscribedGroups ( const std : : list < RsGxsGroupId > & groups )
2013-03-11 20:40:28 +00:00
{
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::request_SpecificSubscribedGroups() " ;
std : : cerr < < std : : endl ;
2013-03-11 20:40:28 +00:00
# endif // GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_META ;
2013-03-11 20:40:28 +00:00
2013-03-16 12:31:31 +00:00
uint32_t token = 0 ;
2013-03-11 20:40:28 +00:00
2020-05-03 23:20:13 +02:00
if ( ! RsGenExchange : : getTokenService ( ) - > requestGroupInfo ( token , ansType , opts , groups ) )
2018-10-29 05:50:11 +01:00
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Failed requesting groups info! "
< < std : : endl ;
return ;
}
if ( ! GxsTokenQueue : : queueRequest ( token , GXSCHANNELS_SUBSCRIBED_META ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Failed queuing request! "
< < std : : endl ;
}
2013-03-11 20:40:28 +00:00
}
void p3GxsChannels : : load_SubscribedGroups ( const uint32_t & token )
{
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::load_SubscribedGroups() " ;
std : : cerr < < std : : endl ;
2013-03-11 20:40:28 +00:00
# endif // GXSCHANNELS_DEBUG
std : : list < RsGroupMetaData > groups ;
std : : list < RsGxsGroupId > groupList ;
getGroupMeta ( token , groups ) ;
std : : list < RsGroupMetaData > : : iterator it ;
2014-10-24 22:07:26 +00:00
for ( it = groups . begin ( ) ; it ! = groups . end ( ) ; + + it )
2013-03-11 20:40:28 +00:00
{
if ( it - > mSubscribeFlags &
( GXS_SERV : : GROUP_SUBSCRIBE_ADMIN |
GXS_SERV : : GROUP_SUBSCRIBE_PUBLISH |
GXS_SERV : : GROUP_SUBSCRIBE_SUBSCRIBED ) )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::load_SubscribedGroups() updating Subscribed Group: " < < it - > mGroupId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
updateSubscribedGroup ( * it ) ;
2015-07-07 00:52:52 +00:00
bool enabled = false ;
if ( autoDownloadEnabled ( it - > mGroupId , enabled ) & & enabled )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::load_SubscribedGroups() remembering AutoDownload Group: " < < it - > mGroupId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
groupList . push_back ( it - > mGroupId ) ;
}
}
else
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::load_SubscribedGroups() clearing unsubscribed Group: " < < it - > mGroupId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
clearUnsubscribedGroup ( it - > mGroupId ) ;
}
}
/* Query for UNPROCESSED POSTS from checkGroupList */
request_GroupUnprocessedPosts ( groupList ) ;
}
void p3GxsChannels : : updateSubscribedGroup ( const RsGroupMetaData & group )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::updateSubscribedGroup() id: " < < group . mGroupId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mSubscribedGroupsMutex ) ;
2013-03-11 20:40:28 +00:00
mSubscribedGroups [ group . mGroupId ] = group ;
}
void p3GxsChannels : : clearUnsubscribedGroup ( const RsGxsGroupId & id )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::clearUnsubscribedGroup() id: " < < id ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mSubscribedGroupsMutex ) ;
2013-03-11 20:40:28 +00:00
std : : map < RsGxsGroupId , RsGroupMetaData > : : iterator it ;
it = mSubscribedGroups . find ( id ) ;
if ( it ! = mSubscribedGroups . end ( ) )
{
mSubscribedGroups . erase ( it ) ;
}
}
2013-03-24 16:32:20 +00:00
bool p3GxsChannels : : subscribeToGroup ( uint32_t & token , const RsGxsGroupId & groupId , bool subscribe )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::subscribedToGroup() id: " < < groupId < < " subscribe: " < < subscribe ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
std : : list < RsGxsGroupId > groups ;
groups . push_back ( groupId ) ;
// Call down to do the real work.
2013-03-24 16:32:20 +00:00
bool response = RsGenExchange : : subscribeToGroup ( token , groupId , subscribe ) ;
2013-03-11 20:40:28 +00:00
// reload Group afterwards.
request_SpecificSubscribedGroups ( groups ) ;
2013-03-24 16:32:20 +00:00
return response ;
2013-03-11 20:40:28 +00:00
}
void p3GxsChannels : : request_SpecificUnprocessedPosts ( std : : list < std : : pair < RsGxsGroupId , RsGxsMessageId > > & ids )
{
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::request_SpecificUnprocessedPosts() " ;
std : : cerr < < std : : endl ;
2013-03-11 20:40:28 +00:00
# endif // GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_DATA ;
2013-03-11 20:40:28 +00:00
2013-06-04 21:00:43 +00:00
// Only Fetch UNPROCESSED messages.
opts . mStatusFilter = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
opts . mStatusMask = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
2013-03-16 12:31:31 +00:00
uint32_t token = 0 ;
2013-03-11 20:40:28 +00:00
2013-03-15 20:46:49 +00:00
/* organise Ids how they want them */
2013-03-16 12:31:31 +00:00
GxsMsgReq msgIds ;
2013-03-15 20:46:49 +00:00
std : : list < std : : pair < RsGxsGroupId , RsGxsMessageId > > : : iterator it ;
2014-10-24 22:07:26 +00:00
for ( it = ids . begin ( ) ; it ! = ids . end ( ) ; + + it )
2018-06-21 15:46:59 +02:00
msgIds [ it - > first ] . insert ( it - > second ) ;
2013-03-15 20:46:49 +00:00
2013-03-16 12:31:31 +00:00
RsGenExchange : : getTokenService ( ) - > requestMsgInfo ( token , ansType , opts , msgIds ) ;
GxsTokenQueue : : queueRequest ( token , GXSCHANNELS_UNPROCESSED_SPECIFIC ) ;
2013-03-11 20:40:28 +00:00
}
void p3GxsChannels : : request_GroupUnprocessedPosts ( const std : : list < RsGxsGroupId > & grouplist )
{
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::request_GroupUnprocessedPosts() " ;
std : : cerr < < std : : endl ;
2013-03-11 20:40:28 +00:00
# endif // GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_DATA ;
2013-03-11 20:40:28 +00:00
2013-06-04 21:00:43 +00:00
// Only Fetch UNPROCESSED messages.
opts . mStatusFilter = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
opts . mStatusMask = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
2013-03-16 12:31:31 +00:00
uint32_t token = 0 ;
2013-03-11 20:40:28 +00:00
2013-03-16 12:31:31 +00:00
RsGenExchange : : getTokenService ( ) - > requestMsgInfo ( token , ansType , opts , grouplist ) ;
GxsTokenQueue : : queueRequest ( token , GXSCHANNELS_UNPROCESSED_GENERIC ) ;
2013-03-11 20:40:28 +00:00
}
2018-11-09 21:24:31 +01:00
void p3GxsChannels : : load_unprocessedPosts ( uint32_t token )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2018-10-29 05:50:11 +01:00
std : : cerr < < " p3GxsChannels::load_SpecificUnprocessedPosts " < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-16 12:31:31 +00:00
2013-03-11 20:40:28 +00:00
std : : vector < RsGxsChannelPost > posts ;
2013-03-15 20:46:49 +00:00
if ( ! getPostData ( token , posts ) )
2013-03-11 20:40:28 +00:00
{
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " ERROR getting post data! "
< < std : : endl ;
2013-03-11 20:40:28 +00:00
return ;
}
std : : vector < RsGxsChannelPost > : : iterator it ;
2014-10-24 22:07:26 +00:00
for ( it = posts . begin ( ) ; it ! = posts . end ( ) ; + + it )
2013-03-11 20:40:28 +00:00
{
/* autodownload the files */
handleUnprocessedPost ( * it ) ;
}
}
void p3GxsChannels : : handleUnprocessedPost ( const RsGxsChannelPost & msg )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " GroupId: " < < msg . mMeta . mGroupId
< < " MsgId: " < < msg . mMeta . mMsgId < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-16 12:31:31 +00:00
if ( ! IS_MSG_UNPROCESSED ( msg . mMeta . mMsgStatus ) )
{
2018-11-09 21:24:31 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " ERROR Msg already Processed! "
< < " mMsgId: " < < msg . mMeta . mMsgId < < std : : endl ;
2013-03-16 12:31:31 +00:00
return ;
}
2013-03-11 20:40:28 +00:00
/* check that autodownload is set */
2018-10-29 05:50:11 +01:00
bool enabled = false ;
if ( autoDownloadEnabled ( msg . mMeta . mGroupId , enabled ) & & enabled )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " AutoDownload Enabled... handling "
< < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
/* check the date is not too old */
2018-10-07 01:34:05 +02:00
rstime_t age = time ( NULL ) - msg . mMeta . mPublishTs ;
2013-03-11 20:40:28 +00:00
2018-10-07 01:34:05 +02:00
if ( age < ( rstime_t ) CHANNEL_DOWNLOAD_PERIOD )
2015-07-07 00:52:52 +00:00
{
/* start download */
// NOTE WE DON'T HANDLE PRIVATE CHANNELS HERE.
// MORE THOUGHT HAS TO GO INTO THAT STUFF.
2013-03-11 20:40:28 +00:00
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " START DOWNLOAD " < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2015-07-07 00:52:52 +00:00
std : : list < RsGxsFile > : : const_iterator fit ;
for ( fit = msg . mFiles . begin ( ) ; fit ! = msg . mFiles . end ( ) ; + + fit )
{
std : : string fname = fit - > mName ;
Sha1CheckSum hash = Sha1CheckSum ( fit - > mHash ) ;
uint64_t size = fit - > mSize ;
std : : list < RsPeerId > srcIds ;
std : : string localpath = " " ;
TransferRequestFlags flags = RS_FILE_REQ_BACKGROUND | RS_FILE_REQ_ANONYMOUS_ROUTING ;
if ( size < CHANNEL_MAX_AUTO_DL )
{
std : : string directory ;
if ( getChannelDownloadDirectory ( msg . mMeta . mGroupId , directory ) )
localpath = directory ;
rsFiles - > FileRequest ( fname , hash , size , localpath , flags , srcIds ) ;
}
2018-10-29 05:50:11 +01:00
else
std : : cerr < < __PRETTY_FUNCTION__ < < " Channel file is not auto- "
< < " downloaded because its size exceeds the threshold "
< < " of " < < CHANNEL_MAX_AUTO_DL < < " bytes. "
< < std : : endl ;
2015-07-07 00:52:52 +00:00
}
}
2013-03-11 20:40:28 +00:00
/* mark as processed */
uint32_t token ;
RsGxsGrpMsgIdPair msgId ( msg . mMeta . mGroupId , msg . mMeta . mMsgId ) ;
setMessageProcessedStatus ( token , msgId , true ) ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-11 20:40:28 +00:00
else
{
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::handleUnprocessedPost() AutoDownload Disabled ... skipping " ;
std : : cerr < < std : : endl ;
2013-03-11 20:40:28 +00:00
}
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
}
2013-03-16 12:31:31 +00:00
// Overloaded from GxsTokenQueue for Request callbacks.
2020-11-30 09:08:29 +01:00
void p3GxsChannels : : handleResponse ( uint32_t token , uint32_t req_type
, RsTokenService : : GxsRequestStatus status )
2013-03-11 20:40:28 +00:00
{
# ifdef GXSCHANNELS_DEBUG
2020-11-30 09:08:29 +01:00
std : : cerr < < " p3GxsChannels::handleResponse( " < < token < < " , " < < req_type < < " , " < < status < < " ) " < < std : : endl ;
2013-03-11 20:40:28 +00:00
# endif // GXSCHANNELS_DEBUG
2020-11-30 09:08:29 +01:00
if ( status ! = RsTokenService : : COMPLETE )
return ; //For now, only manage Complete request
2013-03-11 20:40:28 +00:00
2013-03-16 12:31:31 +00:00
// stuff.
switch ( req_type )
{
case GXSCHANNELS_SUBSCRIBED_META :
2013-03-11 20:40:28 +00:00
load_SubscribedGroups ( token ) ;
2013-03-16 12:31:31 +00:00
break ;
2013-03-11 20:40:28 +00:00
2018-11-09 21:24:31 +01:00
case GXSCHANNELS_UNPROCESSED_SPECIFIC :
load_unprocessedPosts ( token ) ;
break ;
2013-03-11 20:40:28 +00:00
2018-11-09 21:24:31 +01:00
case GXSCHANNELS_UNPROCESSED_GENERIC :
load_unprocessedPosts ( token ) ;
break ;
2013-03-16 12:31:31 +00:00
2018-11-09 21:24:31 +01:00
default :
std : : cerr < < __PRETTY_FUNCTION__ < < " ERROR Unknown Request Type: "
< < req_type < < std : : endl ;
break ;
2013-03-16 12:31:31 +00:00
}
2013-03-11 20:40:28 +00:00
}
2018-06-26 13:20:24 +02:00
////////////////////////////////////////////////////////////////////////////////
/// Blocking API implementation begin
////////////////////////////////////////////////////////////////////////////////
bool p3GxsChannels : : getChannelsSummaries (
std : : list < RsGroupMetaData > & channels )
{
uint32_t token ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_META ;
if ( ! requestGroupInfo ( token , opts )
| | waitToken ( token ) ! = RsTokenService : : COMPLETE ) return false ;
return getGroupSummary ( token , channels ) ;
}
2020-03-21 15:25:34 +01:00
bool p3GxsChannels : : getChannelsInfo ( const std : : list < RsGxsGroupId > & chanIds , std : : vector < RsGxsChannelGroup > & channelsInfo )
2018-06-26 13:20:24 +02:00
{
uint32_t token ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_GROUP_DATA ;
2020-03-21 15:25:34 +01:00
if ( chanIds . empty ( ) )
{
if ( ! requestGroupInfo ( token , opts ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
return false ;
}
else
{
if ( ! requestGroupInfo ( token , opts , chanIds ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
return false ;
}
2019-09-27 16:21:08 +02:00
return getGroupData ( token , channelsInfo ) & & ! channelsInfo . empty ( ) ;
2018-06-26 13:20:24 +02:00
}
2020-03-22 21:47:14 +01:00
bool p3GxsChannels : : getChannelStatistics ( const RsGxsGroupId & channelId , GxsGroupStatistic & stat )
{
uint32_t token ;
if ( ! RsGxsIfaceHelper : : requestGroupStatistic ( token , channelId ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
return false ;
return RsGenExchange : : getGroupStatistic ( token , stat ) ;
}
2020-04-04 22:54:54 +02:00
bool p3GxsChannels : : getChannelServiceStatistics ( GxsServiceStatistic & stat )
{
uint32_t token ;
if ( ! RsGxsIfaceHelper : : requestServiceStatistic ( token ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
return false ;
return RsGenExchange : : getServiceStatistic ( token , stat ) ;
}
2018-12-12 21:35:31 +01:00
bool p3GxsChannels : : getContentSummaries (
const RsGxsGroupId & channelId , std : : vector < RsMsgMetaData > & summaries )
{
uint32_t token ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_META ;
std : : list < RsGxsGroupId > channelIds ;
channelIds . push_back ( channelId ) ;
if ( ! requestMsgInfo ( token , opts , channelIds ) | |
waitToken ( token , std : : chrono : : seconds ( 5 ) ) ! = RsTokenService : : COMPLETE )
return false ;
GxsMsgMetaMap metaMap ;
bool res = RsGenExchange : : getMsgMeta ( token , metaMap ) ;
summaries = metaMap [ channelId ] ;
return res ;
}
2020-03-31 20:21:16 +02:00
bool p3GxsChannels : : getChannelAllContent ( const RsGxsGroupId & channelId ,
std : : vector < RsGxsChannelPost > & posts ,
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsComment > & comments ,
std : : vector < RsGxsVote > & votes )
2020-03-31 20:21:16 +02:00
{
uint32_t token ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_DATA ;
2020-04-27 17:24:36 +02:00
if ( ! requestMsgInfo ( token , opts , std : : list < RsGxsGroupId > ( { channelId } ) ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
return false ;
2020-03-31 20:21:16 +02:00
2020-04-27 17:24:36 +02:00
return getPostData ( token , posts , comments , votes ) ;
2020-03-31 20:21:16 +02:00
}
2018-12-12 21:35:31 +01:00
bool p3GxsChannels : : getChannelContent ( const RsGxsGroupId & channelId ,
2020-03-31 20:21:16 +02:00
const std : : set < RsGxsMessageId > & contentIds ,
std : : vector < RsGxsChannelPost > & posts ,
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsComment > & comments ,
std : : vector < RsGxsVote > & votes )
2018-06-26 13:20:24 +02:00
{
uint32_t token ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_DATA ;
2018-12-12 21:35:31 +01:00
GxsMsgReq msgIds ;
2020-03-31 20:21:16 +02:00
msgIds [ channelId ] = contentIds ;
2018-12-12 21:35:31 +01:00
2020-03-31 20:21:16 +02:00
if ( ! requestMsgInfo ( token , opts , msgIds ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
2020-04-28 00:51:56 +02:00
return false ;
2018-12-12 21:35:31 +01:00
2020-04-27 17:24:36 +02:00
return getPostData ( token , posts , comments , votes ) ;
2018-06-26 13:20:24 +02:00
}
2020-04-28 00:51:56 +02:00
bool p3GxsChannels : : getChannelComments ( const RsGxsGroupId & channelId ,
const std : : set < RsGxsMessageId > & contentIds ,
std : : vector < RsGxsComment > & comments )
{
std : : vector < RsGxsGrpMsgIdPair > msgIds ;
for ( auto & msg : contentIds )
msgIds . push_back ( RsGxsGrpMsgIdPair ( channelId , msg ) ) ;
RsTokReqOptions opts ;
opts . mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA ;
opts . mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST ;
uint32_t token ;
if ( ! requestMsgRelatedInfo ( token , opts , msgIds ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
return false ;
return getRelatedComments ( token , comments ) ;
}
2019-04-05 01:43:23 +02:00
bool p3GxsChannels : : createChannelV2 (
const std : : string & name , const std : : string & description ,
const RsGxsImage & thumbnail , const RsGxsId & authorId ,
RsGxsCircleType circleType , const RsGxsCircleId & circleId ,
RsGxsGroupId & channelId , std : : string & errorMessage )
2019-03-30 22:53:14 +01:00
{
2019-10-05 15:53:46 +02:00
const auto fname = __PRETTY_FUNCTION__ ;
const auto failure = [ & ] ( const std : : string & err )
{
errorMessage = err ;
RsErr ( ) < < fname < < " " < < err < < std : : endl ;
return false ;
} ;
if ( ! authorId . isNull ( ) & & ! rsIdentity - > isOwnId ( authorId ) )
return failure ( " authorId must be either null, or of an owned identity " ) ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
if ( circleType ! = RsGxsCircleType : : PUBLIC
& & circleType ! = RsGxsCircleType : : EXTERNAL
& & circleType ! = RsGxsCircleType : : NODES_GROUP
& & circleType ! = RsGxsCircleType : : LOCAL
& & circleType ! = RsGxsCircleType : : YOUR_EYES_ONLY )
2019-10-05 15:53:46 +02:00
return failure ( " circleType has invalid value " ) ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
switch ( circleType )
{
case RsGxsCircleType : : EXTERNAL :
if ( circleId . isNull ( ) )
2019-10-05 15:53:46 +02:00
return failure ( " circleType is EXTERNAL but circleId is null " ) ;
2019-03-30 22:53:14 +01:00
break ;
2019-04-05 01:43:23 +02:00
case RsGxsCircleType : : NODES_GROUP :
{
RsGroupInfo ginfo ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
if ( ! rsPeers - > getGroupInfo ( RsNodeGroupId ( circleId ) , ginfo ) )
2019-10-05 15:53:46 +02:00
return failure ( " circleType is NODES_GROUP but circleId does not "
" correspond to an actual group of friends " ) ;
2019-03-30 22:53:14 +01:00
break ;
2019-04-05 01:43:23 +02:00
}
default :
if ( ! circleId . isNull ( ) )
2019-10-05 15:53:46 +02:00
return failure ( " circleType requires a null circleId, but a non "
" null circleId ( " + circleId . toStdString ( ) +
" ) was supplied " ) ;
2019-04-05 01:43:23 +02:00
break ;
}
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
// Create a consistent channel group meta from the information supplied
RsGxsChannelGroup channel ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
channel . mMeta . mGroupName = name ;
channel . mMeta . mAuthorId = authorId ;
channel . mMeta . mCircleType = static_cast < uint32_t > ( circleType ) ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
channel . mMeta . mSignFlags = GXS_SERV : : FLAG_GROUP_SIGN_PUBLISH_NONEREQ
| GXS_SERV : : FLAG_AUTHOR_AUTHENTICATION_REQUIRED ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
channel . mMeta . mGroupFlags = GXS_SERV : : FLAG_PRIVACY_PUBLIC ;
2019-03-30 22:53:14 +01:00
channel . mMeta . mCircleId . clear ( ) ;
channel . mMeta . mInternalCircle . clear ( ) ;
2019-04-05 01:43:23 +02:00
switch ( circleType )
{
case RsGxsCircleType : : NODES_GROUP :
channel . mMeta . mInternalCircle = circleId ; break ;
case RsGxsCircleType : : EXTERNAL :
channel . mMeta . mCircleId = circleId ; break ;
default : break ;
}
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
// Create the channel
channel . mDescription = description ;
channel . mImage = thumbnail ;
2019-03-30 22:53:14 +01:00
uint32_t token ;
if ( ! createGroup ( token , channel ) )
2019-10-05 15:53:46 +02:00
return failure ( " Failure creating GXS group " ) ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
// wait for the group creation to complete.
2019-04-12 22:14:16 +02:00
RsTokenService : : GxsRequestStatus wSt =
2019-10-05 15:53:46 +02:00
waitToken ( token , std : : chrono : : seconds ( 5 ) ,
std : : chrono : : milliseconds ( 50 ) ) ;
2019-04-05 01:43:23 +02:00
if ( wSt ! = RsTokenService : : COMPLETE )
2019-10-05 15:53:46 +02:00
return failure ( " GXS operation waitToken failed with: " +
std : : to_string ( wSt ) ) ;
2019-03-30 22:53:14 +01:00
if ( ! RsGenExchange : : getPublishedGroupMeta ( token , channel . mMeta ) )
2019-10-05 15:53:46 +02:00
return failure ( " Failure getting updated group data. " ) ;
2019-03-30 22:53:14 +01:00
2019-04-05 01:43:23 +02:00
channelId = channel . mMeta . mGroupId ;
2019-03-30 22:53:14 +01:00
2019-06-20 17:24:18 +02:00
# ifdef RS_DEEP_CHANNEL_INDEX
DeepChannelsIndex : : indexChannelGroup ( channel ) ;
# endif // RS_DEEP_CHANNEL_INDEX
2019-03-30 22:53:14 +01:00
return true ;
}
2018-10-04 23:36:01 +02:00
bool p3GxsChannels : : createChannel ( RsGxsChannelGroup & channel )
{
uint32_t token ;
2018-11-01 07:04:01 +01:00
if ( ! createGroup ( token , channel ) )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failed creating group. "
2018-11-01 07:04:01 +01:00
< < std : : endl ;
return false ;
}
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! GXS operation failed. "
2018-11-01 07:04:01 +01:00
< < std : : endl ;
2018-10-10 06:40:56 +02:00
return false ;
2018-11-01 07:04:01 +01:00
}
2018-10-10 06:40:56 +02:00
2018-11-01 07:04:01 +01:00
if ( ! RsGenExchange : : getPublishedGroupMeta ( token , channel . mMeta ) )
2018-10-10 06:40:56 +02:00
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failure getting updated "
2018-11-01 07:04:01 +01:00
< < " group data. " < < std : : endl ;
return false ;
}
2019-06-20 17:24:18 +02:00
# ifdef RS_DEEP_CHANNEL_INDEX
DeepChannelsIndex : : indexChannelGroup ( channel ) ;
# endif // RS_DEEP_CHANNEL_INDEX
2018-10-04 23:36:01 +02:00
2018-11-01 07:04:01 +01:00
return true ;
}
2019-04-05 01:43:23 +02:00
bool p3GxsChannels : : createVoteV2 (
const RsGxsGroupId & channelId , const RsGxsMessageId & postId ,
const RsGxsMessageId & commentId , const RsGxsId & authorId ,
RsGxsVoteType tVote , RsGxsMessageId & voteId , std : : string & errorMessage )
2018-11-16 17:50:34 +01:00
{
2019-03-31 22:11:09 +02:00
std : : vector < RsGxsChannelGroup > channelsInfo ;
2019-04-05 01:43:23 +02:00
if ( ! getChannelsInfo ( std : : list < RsGxsGroupId > ( { channelId } ) , channelsInfo ) )
{
errorMessage = " Channel with Id " + channelId . toStdString ( )
+ " does not exist. " ;
return false ;
}
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
if ( commentId . isNull ( ) )
{
errorMessage = " You cannot vote on null comment "
+ commentId . toStdString ( ) ;
2018-11-16 17:50:34 +01:00
return false ;
2019-04-05 01:43:23 +02:00
}
2018-11-16 17:50:34 +01:00
2019-04-05 01:43:23 +02:00
std : : set < RsGxsMessageId > s ( { commentId } ) ;
2019-03-31 22:11:09 +02:00
std : : vector < RsGxsChannelPost > posts ;
std : : vector < RsGxsComment > comments ;
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsVote > votes ;
2019-03-31 22:11:09 +02:00
2020-04-27 17:24:36 +02:00
if ( ! getChannelContent ( channelId , s , posts , comments , votes ) )
2018-11-16 17:50:34 +01:00
{
2019-04-05 01:43:23 +02:00
errorMessage = " You cannot vote on comment "
+ commentId . toStdString ( ) + " of channel with Id "
+ channelId . toStdString ( )
+ " : this comment does not exists locally! " ;
2018-11-16 17:50:34 +01:00
return false ;
}
2019-04-05 01:43:23 +02:00
// is the ID a comment ID or a post ID?
// It should be comment => should have a parent ID
if ( posts . front ( ) . mMeta . mParentId . isNull ( ) )
2018-11-16 17:50:34 +01:00
{
2019-04-05 01:43:23 +02:00
errorMessage = " You cannot vote on channel message "
+ commentId . toStdString ( ) + " of channel with Id "
+ channelId . toStdString ( )
+ " : given id refers to a post, not a comment! " ;
2018-11-16 17:50:34 +01:00
return false ;
}
2019-04-05 01:43:23 +02:00
if ( tVote ! = RsGxsVoteType : : NONE
& & tVote ! = RsGxsVoteType : : UP
& & tVote ! = RsGxsVoteType : : DOWN )
{
errorMessage = " Your vote to channel with Id "
+ channelId . toStdString ( ) + " has wrong vote type. "
+ " Only RsGxsVoteType::NONE, RsGxsVoteType::UP, "
+ " RsGxsVoteType::DOWN are accepted. " ;
2019-03-31 22:11:09 +02:00
return false ;
2019-04-05 01:43:23 +02:00
}
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
if ( ! rsIdentity - > isOwnId ( authorId ) )
{
errorMessage = " You cannot vote to channel with Id "
+ channelId . toStdString ( ) + " with identity "
+ authorId . toStdString ( ) + " because it is not yours. " ;
2019-03-31 22:11:09 +02:00
return false ;
2019-04-05 01:43:23 +02:00
}
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
// Create the vote
2019-03-31 22:11:09 +02:00
RsGxsVote vote ;
2019-04-05 01:43:23 +02:00
vote . mMeta . mGroupId = channelId ;
vote . mMeta . mThreadId = postId ;
vote . mMeta . mParentId = commentId ;
2019-03-31 22:11:09 +02:00
vote . mMeta . mAuthorId = authorId ;
2019-04-05 01:43:23 +02:00
vote . mVoteType = static_cast < uint32_t > ( tVote ) ;
uint32_t token ;
if ( ! createNewVote ( token , vote ) )
{
errorMessage = " Error! Failed creating vote. " ;
return false ;
}
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
errorMessage = " GXS operation failed. " ;
return false ;
}
if ( ! RsGenExchange : : getPublishedMsgMeta ( token , vote . mMeta ) )
{
errorMessage = " Failure getting generated vote data. " ;
return false ;
}
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
voteId = vote . mMeta . mMsgId ;
return true ;
}
2018-11-16 17:50:34 +01:00
2019-04-05 01:43:23 +02:00
/// @deprecated use createVoteV2 instead
bool p3GxsChannels : : createVote ( RsGxsVote & vote )
{
2018-11-16 17:50:34 +01:00
uint32_t token ;
2019-02-14 21:58:33 +01:00
if ( ! createNewVote ( token , vote ) )
2018-11-16 17:50:34 +01:00
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failed creating vote. "
< < std : : endl ;
2018-11-16 17:50:34 +01:00
return false ;
}
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! GXS operation failed. "
< < std : : endl ;
2018-11-16 17:50:34 +01:00
return false ;
}
if ( ! RsGenExchange : : getPublishedMsgMeta ( token , vote . mMeta ) )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failure getting generated "
< < " vote data. " < < std : : endl ;
2018-11-16 17:50:34 +01:00
return false ;
}
return true ;
}
2018-11-01 07:04:01 +01:00
bool p3GxsChannels : : editChannel ( RsGxsChannelGroup & channel )
{
uint32_t token ;
if ( ! updateGroup ( token , channel ) )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failed updating group. "
2018-11-01 07:04:01 +01:00
< < std : : endl ;
return false ;
2018-10-16 22:40:27 +02:00
}
2018-11-01 07:04:01 +01:00
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! GXS operation failed. "
2018-11-01 07:04:01 +01:00
< < std : : endl ;
return false ;
}
if ( ! RsGenExchange : : getPublishedGroupMeta ( token , channel . mMeta ) )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failure getting updated "
2018-11-01 07:04:01 +01:00
< < " group data. " < < std : : endl ;
return false ;
}
2019-06-20 17:24:18 +02:00
# ifdef RS_DEEP_CHANNEL_INDEX
DeepChannelsIndex : : indexChannelGroup ( channel ) ;
# endif // RS_DEEP_CHANNEL_INDEX
2018-11-01 07:04:01 +01:00
return true ;
2018-10-04 23:36:01 +02:00
}
2019-04-05 01:43:23 +02:00
bool p3GxsChannels : : createPostV2 (
const RsGxsGroupId & channelId , const std : : string & title ,
const std : : string & body , const std : : list < RsGxsFile > & files ,
const RsGxsImage & thumbnail , const RsGxsMessageId & origPostId ,
RsGxsMessageId & postId , std : : string & errorMessage )
2018-10-04 23:36:01 +02:00
{
2019-03-31 22:11:09 +02:00
// Do some checks
std : : vector < RsGxsChannelGroup > channelsInfo ;
2019-04-05 01:43:23 +02:00
if ( ! getChannelsInfo ( std : : list < RsGxsGroupId > ( { channelId } ) , channelsInfo ) )
{
errorMessage = " Channel with Id " + channelId . toStdString ( ) +
" does not exist. " ;
return false ;
}
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
const RsGxsChannelGroup & cg ( * channelsInfo . begin ( ) ) ;
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
if ( ! ( cg . mMeta . mSubscribeFlags & GXS_SERV : : GROUP_SUBSCRIBE_PUBLISH ) )
{
errorMessage = " You cannot post to channel with Id " +
channelId . toStdString ( ) + " : missing publish rights! " ;
return false ;
}
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
if ( ! origPostId . isNull ( ) )
2019-03-31 22:11:09 +02:00
{
2019-04-05 01:43:23 +02:00
std : : set < RsGxsMessageId > s ( { origPostId } ) ;
2019-03-31 22:11:09 +02:00
std : : vector < RsGxsChannelPost > posts ;
std : : vector < RsGxsComment > comments ;
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsVote > votes ;
2019-03-31 22:11:09 +02:00
2020-04-27 17:24:36 +02:00
if ( ! getChannelContent ( channelId , s , posts , comments , votes ) )
2019-04-05 01:43:23 +02:00
{
errorMessage = " You cannot edit post " + origPostId . toStdString ( )
+ " of channel with Id " + channelId . toStdString ( )
+ " : this post does not exist locally! " ;
2019-03-31 22:11:09 +02:00
return false ;
2019-04-05 01:43:23 +02:00
}
2019-03-31 22:11:09 +02:00
}
// Create the post
RsGxsChannelPost post ;
2019-04-05 01:43:23 +02:00
post . mMeta . mGroupId = channelId ;
post . mMeta . mOrigMsgId = origPostId ;
post . mMeta . mMsgName = title ;
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
post . mMsg = body ;
post . mFiles = files ;
post . mThumbnail = thumbnail ;
2019-03-31 22:11:09 +02:00
2018-10-04 23:36:01 +02:00
uint32_t token ;
2019-04-05 01:43:23 +02:00
if ( ! createPost ( token , post ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
errorMessage = " GXS operation failed " ;
return false ;
}
2018-10-04 23:36:01 +02:00
2018-10-16 22:40:27 +02:00
if ( RsGenExchange : : getPublishedMsgMeta ( token , post . mMeta ) )
2018-10-10 06:40:56 +02:00
{
2019-06-20 17:24:18 +02:00
# ifdef RS_DEEP_CHANNEL_INDEX
DeepChannelsIndex : : indexChannelPost ( post ) ;
# endif // RS_DEEP_CHANNEL_INDEX
2018-10-10 06:40:56 +02:00
2019-04-05 01:43:23 +02:00
postId = post . mMeta . mMsgId ;
2018-10-16 22:40:27 +02:00
return true ;
}
2019-04-05 01:43:23 +02:00
errorMessage = " Failed to retrive created post metadata " ;
2018-10-20 14:07:39 +02:00
return false ;
2018-10-04 23:36:01 +02:00
}
2019-07-30 18:50:56 +02:00
bool p3GxsChannels : : createCommentV2 (
const RsGxsGroupId & channelId ,
const RsGxsMessageId & threadId ,
const std : : string & comment ,
const RsGxsId & authorId ,
const RsGxsMessageId & parentId ,
const RsGxsMessageId & origCommentId ,
RsGxsMessageId & commentMessageId ,
std : : string & errorMessage )
2019-03-31 22:11:09 +02:00
{
2019-10-07 18:37:44 +02:00
constexpr auto fname = __PRETTY_FUNCTION__ ;
const auto failure = [ & ] ( const std : : string & err )
2019-04-05 01:43:23 +02:00
{
2019-10-07 18:37:44 +02:00
errorMessage = err ;
RsErr ( ) < < fname < < " " < < err < < std : : endl ;
2019-04-05 01:43:23 +02:00
return false ;
2019-10-07 18:37:44 +02:00
} ;
if ( channelId . isNull ( ) ) return failure ( " channelId cannot be null " ) ;
if ( threadId . isNull ( ) ) return failure ( " threadId cannot be null " ) ;
if ( parentId . isNull ( ) ) return failure ( " parentId cannot be null " ) ;
std : : vector < RsGxsChannelGroup > channelsInfo ;
if ( ! getChannelsInfo ( std : : list < RsGxsGroupId > ( { channelId } ) , channelsInfo ) )
return failure ( " Channel with Id " + channelId . toStdString ( )
+ " does not exist. " ) ;
2019-03-31 22:11:09 +02:00
2019-04-11 21:04:13 +02:00
std : : vector < RsGxsChannelPost > posts ;
std : : vector < RsGxsComment > comments ;
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsVote > votes ;
2019-04-11 21:04:13 +02:00
2019-04-12 22:14:16 +02:00
if ( ! getChannelContent ( // does the post thread exist?
2020-04-27 17:24:36 +02:00
channelId , std : : set < RsGxsMessageId > ( { threadId } ) ,
posts , comments , votes ) )
2019-10-07 18:37:44 +02:00
return failure ( " You cannot comment post " + threadId . toStdString ( ) +
" of channel with Id " + channelId . toStdString ( ) +
" : this post does not exists locally! " ) ;
2019-03-31 22:11:09 +02:00
2019-04-12 22:14:16 +02:00
// check that the post thread Id is actually that of a post thread
if ( posts . size ( ) ! = 1 | | ! posts [ 0 ] . mMeta . mParentId . isNull ( ) )
2019-10-07 18:37:44 +02:00
return failure ( " You cannot comment post " + threadId . toStdString ( ) +
" of channel with Id " + channelId . toStdString ( ) +
" : supplied threadId is not a thread, or parentMsgId is "
" not a comment! " ) ;
2019-04-11 21:04:13 +02:00
2020-04-27 17:24:36 +02:00
if ( ! getChannelContent ( // does the post parent exist?
2019-10-07 18:37:44 +02:00
channelId , std : : set < RsGxsMessageId > ( { parentId } ) ,
2020-04-27 17:24:36 +02:00
posts , comments , votes ) )
2019-10-07 18:37:44 +02:00
return failure ( " You cannot comment post " + parentId . toStdString ( ) +
" : supplied parent doesn't exists locally! " ) ;
2019-07-30 18:50:56 +02:00
if ( ! origCommentId . isNull ( ) )
{
std : : set < RsGxsMessageId > s ( { origCommentId } ) ;
2020-04-27 17:24:36 +02:00
std : : vector < RsGxsComment > cmts ;
2019-07-30 18:50:56 +02:00
2020-04-27 17:24:36 +02:00
if ( ! getChannelContent ( channelId , s , posts , cmts , votes ) | |
2019-07-30 18:50:56 +02:00
comments . size ( ) ! = 1 )
2019-10-07 18:37:44 +02:00
return failure ( " You cannot edit comment " +
origCommentId . toStdString ( ) +
" of channel with Id " + channelId . toStdString ( ) +
" : this comment does not exist locally! " ) ;
2019-03-31 22:11:09 +02:00
2019-07-30 18:50:56 +02:00
const RsGxsId & commentAuthor = comments [ 0 ] . mMeta . mAuthorId ;
if ( commentAuthor ! = authorId )
2019-10-07 18:37:44 +02:00
return failure ( " Editor identity and creator doesn't match "
+ authorId . toStdString ( ) + " != "
+ commentAuthor . toStdString ( ) ) ;
2019-07-30 18:50:56 +02:00
}
if ( ! rsIdentity - > isOwnId ( authorId ) ) // is the author ID actually ours?
2019-10-07 18:37:44 +02:00
return failure ( " You cannot comment to channel with Id " +
channelId . toStdString ( ) + " with identity " +
authorId . toStdString ( ) + " because it is not yours. " ) ;
2019-03-31 22:11:09 +02:00
2019-04-05 01:43:23 +02:00
// Now create the comment
2019-03-31 22:11:09 +02:00
RsGxsComment cmt ;
2019-04-11 21:04:13 +02:00
cmt . mMeta . mGroupId = channelId ;
cmt . mMeta . mThreadId = threadId ;
2019-04-05 01:43:23 +02:00
cmt . mMeta . mParentId = parentId ;
2019-04-11 21:04:13 +02:00
cmt . mMeta . mAuthorId = authorId ;
2019-07-30 18:50:56 +02:00
cmt . mMeta . mOrigMsgId = origCommentId ;
2019-04-11 21:04:13 +02:00
cmt . mComment = comment ;
2019-03-31 22:11:09 +02:00
uint32_t token ;
if ( ! createNewComment ( token , cmt ) )
2019-10-07 18:37:44 +02:00
return failure ( " createNewComment failed " ) ;
2019-03-31 22:11:09 +02:00
2019-10-07 18:37:44 +02:00
RsTokenService : : GxsRequestStatus wSt = waitToken ( token ) ;
if ( wSt ! = RsTokenService : : COMPLETE )
return failure ( " GXS operation waitToken failed with: " +
std : : to_string ( wSt ) ) ;
2019-03-31 22:11:09 +02:00
if ( ! RsGenExchange : : getPublishedMsgMeta ( token , cmt . mMeta ) )
2019-10-07 18:37:44 +02:00
return failure ( " Failure getting created comment data. " ) ;
2019-04-05 01:43:23 +02:00
commentMessageId = cmt . mMeta . mMsgId ;
return true ;
}
bool p3GxsChannels : : createComment ( RsGxsComment & comment ) // deprecated
{
uint32_t token ;
if ( ! createNewComment ( token , comment ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failed creating comment. "
< < std : : endl ;
return false ;
}
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! GXS operation failed. "
< < std : : endl ;
return false ;
}
if ( ! RsGenExchange : : getPublishedMsgMeta ( token , comment . mMeta ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! Failure getting generated "
< < " comment data. " < < std : : endl ;
2019-03-31 22:11:09 +02:00
return false ;
}
return true ;
}
2021-01-24 22:17:02 +01:00
bool p3GxsChannels : : subscribeToChannel ( const RsGxsGroupId & groupId , bool subscribe )
2018-10-29 05:50:11 +01:00
{
uint32_t token ;
2021-01-24 22:17:02 +01:00
if ( ! subscribeToGroup ( token , groupId , subscribe ) | | waitToken ( token ) ! = RsTokenService : : COMPLETE ) return false ;
RsGxsGroupId grpId ;
acknowledgeGrp ( token , grpId ) ;
2018-10-29 05:50:11 +01:00
return true ;
}
2018-11-01 07:04:01 +01:00
bool p3GxsChannels : : markRead ( const RsGxsGrpMsgIdPair & msgId , bool read )
{
uint32_t token ;
setMessageReadStatus ( token , msgId , read ) ;
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE ) return false ;
2021-01-24 22:17:02 +01:00
RsGxsGrpMsgIdPair p ;
acknowledgeMsg ( token , p ) ;
2018-11-01 07:04:01 +01:00
return true ;
}
bool p3GxsChannels : : shareChannelKeys (
const RsGxsGroupId & channelId , const std : : set < RsPeerId > & peers )
{
return groupShareKeys ( channelId , peers ) ;
}
2018-10-04 23:36:01 +02:00
2018-06-26 13:20:24 +02:00
////////////////////////////////////////////////////////////////////////////////
/// Blocking API implementation end
////////////////////////////////////////////////////////////////////////////////
2013-03-11 20:40:28 +00:00
/********************************************************************************************/
/********************************************************************************************/
2016-02-17 19:27:28 +01:00
bool p3GxsChannels : : autoDownloadEnabled ( const RsGxsGroupId & groupId , bool & enabled )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2018-11-02 00:53:32 +01:00
std : : cerr < < " p3GxsChannels::autoDownloadEnabled( " < < groupId < < " ) " ;
2013-03-16 12:31:31 +00:00
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mSubscribedGroupsMutex ) ;
2013-03-11 20:40:28 +00:00
std : : map < RsGxsGroupId , RsGroupMetaData > : : iterator it ;
2016-02-17 19:27:28 +01:00
it = mSubscribedGroups . find ( groupId ) ;
2013-03-16 12:31:31 +00:00
if ( it = = mSubscribedGroups . end ( ) )
2013-03-11 20:40:28 +00:00
{
2018-11-02 00:53:32 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " WARNING requested channel: "
< < groupId < < " is not subscribed " < < std : : endl ;
2013-03-11 20:40:28 +00:00
return false ;
}
/* extract from ServiceString */
2020-11-06 23:08:18 +01:00
GxsChannelGroupInfo ss ;
2013-03-11 20:40:28 +00:00
ss . load ( it - > second . mServiceString ) ;
2016-02-17 19:27:28 +01:00
enabled = ss . mAutoDownload ;
2013-03-11 20:40:28 +00:00
2016-02-17 19:27:28 +01:00
return true ;
2015-07-07 00:52:52 +00:00
}
2013-03-11 20:40:28 +00:00
2020-11-06 23:08:18 +01:00
bool GxsChannelGroupInfo : : load ( const std : : string & input )
2013-03-11 20:40:28 +00:00
{
2016-02-22 19:07:49 +01:00
if ( input . empty ( ) )
{
# ifdef GXSCHANNELS_DEBUG
std : : cerr < < " SSGxsChannelGroup::load() asked to load a null string. " < < std : : endl ;
# endif
return true ;
}
2015-07-07 00:52:52 +00:00
int download_val ;
mAutoDownload = false ;
mDownloadDirectory . clear ( ) ;
2016-01-12 21:43:04 -05:00
2015-07-07 00:52:52 +00:00
RsTemporaryMemory tmpmem ( input . length ( ) ) ;
if ( 1 = = sscanf ( input . c_str ( ) , " D:%d " , & download_val ) )
{
if ( download_val = = 1 )
mAutoDownload = true ;
}
else if ( 2 = = sscanf ( input . c_str ( ) , " v2 { D : % d } { P : % [ ^ } ] } " ,&download_val,(unsigned char*)tmpmem))
{
if ( download_val = = 1 )
mAutoDownload = true ;
std : : vector < uint8_t > vals = Radix64 : : decode ( std : : string ( ( char * ) ( unsigned char * ) tmpmem ) ) ;
mDownloadDirectory = std : : string ( ( char * ) vals . data ( ) , vals . size ( ) ) ;
}
else if ( 1 = = sscanf ( input . c_str ( ) , " v2 { D : % d } " ,&download_val))
{
if ( download_val = = 1 )
mAutoDownload = true ;
}
else
{
2015-07-09 20:55:11 +00:00
# ifdef GXSCHANNELS_DEBUG
2015-07-07 00:52:52 +00:00
std : : cerr < < " SSGxsChannelGroup::load(): could not parse string \" " < < input < < " \" " < < std : : endl ;
2015-07-09 20:55:11 +00:00
# endif
2015-07-07 00:52:52 +00:00
return false ;
}
2015-07-09 20:55:11 +00:00
# ifdef GXSCHANNELS_DEBUG
2015-07-07 00:52:52 +00:00
std : : cerr < < " DECODED STRING: autoDL= " < < mAutoDownload < < " , directory= \" " < < mDownloadDirectory < < " \" " < < std : : endl ;
2015-07-09 20:55:11 +00:00
# endif
2015-07-07 00:52:52 +00:00
return true ;
2013-03-11 20:40:28 +00:00
}
2020-11-06 23:08:18 +01:00
std : : string GxsChannelGroupInfo : : save ( ) const
2013-03-11 20:40:28 +00:00
{
2015-07-07 00:52:52 +00:00
std : : string output = " v2 " ;
if ( mAutoDownload )
output + = " {D:1} " ;
else
output + = " {D:0} " ;
if ( ! mDownloadDirectory . empty ( ) )
{
std : : string encoded_str ;
2016-05-11 17:59:42 -04:00
Radix64 : : encode ( ( unsigned char * ) mDownloadDirectory . c_str ( ) , mDownloadDirectory . length ( ) , encoded_str ) ;
2015-07-07 00:52:52 +00:00
output + = " {P: " + encoded_str + " } " ;
}
2015-07-09 20:55:11 +00:00
# ifdef GXSCHANNELS_DEBUG
2015-07-07 00:52:52 +00:00
std : : cerr < < " ENCODED STRING: " < < output < < std : : endl ;
2015-07-09 20:55:11 +00:00
# endif
2015-07-07 00:52:52 +00:00
return output ;
2013-03-11 20:40:28 +00:00
}
2018-10-29 05:50:11 +01:00
bool p3GxsChannels : : setAutoDownload ( const RsGxsGroupId & groupId , bool enabled )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " id: " < < groupId
< < " enabled: " < < enabled < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-11 20:40:28 +00:00
2018-10-29 05:50:11 +01:00
RS_STACK_MUTEX ( mSubscribedGroupsMutex ) ;
2013-03-11 20:40:28 +00:00
std : : map < RsGxsGroupId , RsGroupMetaData > : : iterator it ;
it = mSubscribedGroups . find ( groupId ) ;
2013-03-16 12:31:31 +00:00
if ( it = = mSubscribedGroups . end ( ) )
2013-03-11 20:40:28 +00:00
{
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " ERROR requested channel: "
< < groupId . toStdString ( ) < < " is not subscribed! " < < std : : endl ;
2013-03-11 20:40:28 +00:00
return false ;
}
/* extract from ServiceString */
2020-11-06 23:08:18 +01:00
GxsChannelGroupInfo ss ;
2013-03-11 20:40:28 +00:00
ss . load ( it - > second . mServiceString ) ;
if ( enabled = = ss . mAutoDownload )
{
2018-10-29 05:50:11 +01:00
std : : cerr < < __PRETTY_FUNCTION__ < < " WARNING mAutoDownload was already "
< < " properly set to: " < < enabled < < " for channel: "
< < groupId . toStdString ( ) < < std : : endl ;
return false ;
2013-03-11 20:40:28 +00:00
}
ss . mAutoDownload = enabled ;
std : : string serviceString = ss . save ( ) ;
2013-03-16 12:31:31 +00:00
2018-10-29 05:50:11 +01:00
uint32_t token ;
RsGenExchange : : setGroupServiceString ( token , groupId , serviceString ) ;
2013-03-11 20:40:28 +00:00
2018-10-29 05:50:11 +01:00
if ( waitToken ( token ) ! = RsTokenService : : COMPLETE ) return false ;
2013-03-11 20:40:28 +00:00
2018-10-29 05:50:11 +01:00
it - > second . mServiceString = serviceString ; // update Local Cache.
2013-03-11 20:40:28 +00:00
return true ;
}
/********************************************************************************************/
/********************************************************************************************/
void p3GxsChannels : : setMessageProcessedStatus ( uint32_t & token , const RsGxsGrpMsgIdPair & msgId , bool processed )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::setMessageProcessedStatus() " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-16 12:31:31 +00:00
uint32_t mask = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
uint32_t status = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
if ( processed )
{
status = 0 ;
}
setMsgStatusFlags ( token , msgId , status , mask ) ;
2013-03-11 20:40:28 +00:00
}
2018-03-28 16:30:35 +02:00
void p3GxsChannels : : setMessageReadStatus ( uint32_t & token ,
const RsGxsGrpMsgIdPair & msgId ,
bool read )
2013-03-11 20:40:28 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-16 12:31:31 +00:00
std : : cerr < < " p3GxsChannels::setMessageReadStatus() " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-16 12:31:31 +00:00
2014-05-06 20:55:30 +00:00
/* Always remove status unprocessed */
2014-10-12 17:11:37 +00:00
uint32_t mask = GXS_SERV : : GXS_MSG_STATUS_GUI_NEW | GXS_SERV : : GXS_MSG_STATUS_GUI_UNREAD ;
uint32_t status = GXS_SERV : : GXS_MSG_STATUS_GUI_UNREAD ;
2018-03-28 16:30:35 +02:00
if ( read ) status = 0 ;
2013-03-16 12:31:31 +00:00
setMsgStatusFlags ( token , msgId , status , mask ) ;
2013-03-11 20:40:28 +00:00
2020-01-26 23:19:20 +01:00
if ( rsEvents )
{
auto ev = std : : make_shared < RsGxsChannelEvent > ( ) ;
ev - > mChannelMsgId = msgId . second ;
ev - > mChannelGroupId = msgId . first ;
ev - > mChannelEventCode = RsChannelEventCode : : READ_STATUS_CHANGED ;
rsEvents - > postEvent ( ev ) ;
}
}
2013-03-11 20:40:28 +00:00
/********************************************************************************************/
2013-03-04 20:26:48 +00:00
/********************************************************************************************/
bool p3GxsChannels : : createGroup ( uint32_t & token , RsGxsChannelGroup & group )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::createGroup() " < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
RsGxsChannelGroupItem * grpItem = new RsGxsChannelGroupItem ( ) ;
2013-03-11 20:40:28 +00:00
grpItem - > fromChannelGroup ( group , true ) ;
2013-03-04 20:26:48 +00:00
RsGenExchange : : publishGroup ( token , grpItem ) ;
return true ;
}
2014-02-19 11:08:37 +00:00
bool p3GxsChannels : : updateGroup ( uint32_t & token , RsGxsChannelGroup & group )
2014-02-09 10:33:16 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2014-02-09 10:33:16 +00:00
std : : cerr < < " p3GxsChannels::updateGroup() " < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2014-02-09 10:33:16 +00:00
RsGxsChannelGroupItem * grpItem = new RsGxsChannelGroupItem ( ) ;
grpItem - > fromChannelGroup ( group , true ) ;
2014-02-19 11:08:37 +00:00
RsGenExchange : : updateGroup ( token , grpItem ) ;
2014-02-09 10:33:16 +00:00
return true ;
}
2019-04-05 01:43:23 +02:00
/// @deprecated use createPostV2 instead
bool p3GxsChannels : : createPost ( RsGxsChannelPost & post )
{
uint32_t token ;
if ( ! createPost ( token , post )
| | waitToken ( token ) ! = RsTokenService : : COMPLETE ) return false ;
if ( RsGenExchange : : getPublishedMsgMeta ( token , post . mMeta ) )
{
2019-06-20 17:24:18 +02:00
# ifdef RS_DEEP_CHANNEL_INDEX
DeepChannelsIndex : : indexChannelPost ( post ) ;
# endif // RS_DEEP_CHANNEL_INDEX
2019-04-05 01:43:23 +02:00
return true ;
}
return false ;
}
2014-02-09 10:33:16 +00:00
2013-03-04 20:26:48 +00:00
bool p3GxsChannels : : createPost ( uint32_t & token , RsGxsChannelPost & msg )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " GroupId: " < < msg . mMeta . mGroupId
< < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
RsGxsChannelPostItem * msgItem = new RsGxsChannelPostItem ( ) ;
2013-03-11 20:40:28 +00:00
msgItem - > fromChannelPost ( msg , true ) ;
2013-03-04 20:26:48 +00:00
RsGenExchange : : publishMsg ( token , msgItem ) ;
return true ;
}
2013-03-13 00:24:57 +00:00
/********************************************************************************************/
/********************************************************************************************/
2018-06-26 13:20:24 +02:00
bool p3GxsChannels : : ExtraFileHash ( const std : : string & path )
2013-03-13 00:24:57 +00:00
{
2013-03-16 12:31:31 +00:00
TransferRequestFlags flags = RS_FILE_REQ_ANONYMOUS_ROUTING ;
2018-06-26 13:20:24 +02:00
return rsFiles - > ExtraFileHash ( path , GXSCHANNEL_STOREPERIOD , flags ) ;
2013-03-13 00:24:57 +00:00
}
2019-08-01 15:20:54 +02:00
bool p3GxsChannels : : ExtraFileRemove ( const RsFileHash & hash )
{ return rsFiles - > ExtraFileRemove ( hash ) ; }
2013-03-13 00:24:57 +00:00
2013-03-04 20:26:48 +00:00
/********************************************************************************************/
/********************************************************************************************/
/* so we need the same tick idea as wiki for generating dummy channels
*/
2013-03-16 12:31:31 +00:00
# define MAX_GEN_GROUPS 20
# define MAX_GEN_POSTS 500
# define MAX_GEN_COMMENTS 600
# define MAX_GEN_VOTES 700
2013-03-04 20:26:48 +00:00
std : : string p3GxsChannels : : genRandomId ( )
{
2013-03-16 12:31:31 +00:00
std : : string randomId ;
for ( int i = 0 ; i < 20 ; i + + )
{
randomId + = ( char ) ( ' a ' + ( RSRandom : : random_u32 ( ) % 26 ) ) ;
}
2013-03-04 20:26:48 +00:00
2013-03-16 12:31:31 +00:00
return randomId ;
2013-03-04 20:26:48 +00:00
}
bool p3GxsChannels : : generateDummyData ( )
{
mGenCount = 0 ;
2013-03-13 00:24:57 +00:00
mGenRefs . resize ( MAX_GEN_VOTES ) ;
2013-03-04 20:26:48 +00:00
std : : string groupName ;
rs_sprintf ( groupName , " TestChannel_%d " , mGenCount ) ;
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::generateDummyData() Starting off with Group: " < < groupName ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
/* create a new group */
generateGroup ( mGenToken , groupName ) ;
mGenActive = true ;
return true ;
}
void p3GxsChannels : : dummy_tick ( )
{
/* check for a new callback */
if ( mGenActive )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummyTick() Gen Active " ;
2013-03-04 20:26:48 +00:00
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
uint32_t status = RsGenExchange : : getTokenService ( ) - > requestStatus ( mGenToken ) ;
2018-06-24 18:56:48 +02:00
if ( status ! = RsTokenService : : COMPLETE )
2013-03-04 20:26:48 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Status: " < < status ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
2018-06-24 18:56:48 +02:00
if ( status = = RsTokenService : : FAILED )
2013-03-04 20:26:48 +00:00
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() generateDummyMsgs() FAILED " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
mGenActive = false ;
}
return ;
}
if ( mGenCount < MAX_GEN_GROUPS )
{
/* get the group Id */
RsGxsGroupId groupId ;
RsGxsMessageId emptyId ;
if ( ! acknowledgeTokenGrp ( mGenToken , groupId ) )
{
std : : cerr < < " ERROR " ;
std : : cerr < < std : : endl ;
mGenActive = false ;
return ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Acknowledged GroupId: " < < groupId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
ChannelDummyRef ref ( groupId , emptyId , emptyId ) ;
mGenRefs [ mGenCount ] = ref ;
}
2013-03-13 00:24:57 +00:00
else if ( mGenCount < MAX_GEN_POSTS )
{
/* get the msg Id, and generate next snapshot */
RsGxsGrpMsgIdPair msgId ;
if ( ! acknowledgeTokenMsg ( mGenToken , msgId ) )
{
std : : cerr < < " ERROR " ;
std : : cerr < < std : : endl ;
mGenActive = false ;
return ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Acknowledged Post <GroupId: " < < msgId . first < < " , MsgId: " < < msgId . second < < " > " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-13 00:24:57 +00:00
/* store results for later selection */
ChannelDummyRef ref ( msgId . first , mGenThreadId , msgId . second ) ;
mGenRefs [ mGenCount ] = ref ;
}
else if ( mGenCount < MAX_GEN_COMMENTS )
2013-03-04 20:26:48 +00:00
{
/* get the msg Id, and generate next snapshot */
RsGxsGrpMsgIdPair msgId ;
if ( ! acknowledgeTokenMsg ( mGenToken , msgId ) )
{
std : : cerr < < " ERROR " ;
std : : cerr < < std : : endl ;
mGenActive = false ;
return ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Acknowledged Comment <GroupId: " < < msgId . first < < " , MsgId: " < < msgId . second < < " > " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-13 00:24:57 +00:00
/* store results for later selection */
ChannelDummyRef ref ( msgId . first , mGenThreadId , msgId . second ) ;
mGenRefs [ mGenCount ] = ref ;
}
else if ( mGenCount < MAX_GEN_VOTES )
{
/* get the msg Id, and generate next snapshot */
RsGxsGrpMsgIdPair msgId ;
2013-03-15 20:46:49 +00:00
if ( ! acknowledgeVote ( mGenToken , msgId ) )
2013-03-13 00:24:57 +00:00
{
std : : cerr < < " ERROR " ;
std : : cerr < < std : : endl ;
mGenActive = false ;
return ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Acknowledged Vote <GroupId: " < < msgId . first < < " , MsgId: " < < msgId . second < < " > " ;
2013-03-04 20:26:48 +00:00
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
/* store results for later selection */
ChannelDummyRef ref ( msgId . first , mGenThreadId , msgId . second ) ;
mGenRefs [ mGenCount ] = ref ;
}
else
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Finished " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
/* done */
mGenActive = false ;
return ;
}
mGenCount + + ;
if ( mGenCount < MAX_GEN_GROUPS )
{
std : : string groupName ;
rs_sprintf ( groupName , " TestChannel_%d " , mGenCount ) ;
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Generating Group: " < < groupName ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
/* create a new group */
generateGroup ( mGenToken , groupName ) ;
}
2013-03-13 00:24:57 +00:00
else if ( mGenCount < MAX_GEN_POSTS )
2013-03-04 20:26:48 +00:00
{
2013-03-13 00:24:57 +00:00
/* create a new post */
uint32_t idx = ( uint32_t ) ( MAX_GEN_GROUPS * RSRandom : : random_f32 ( ) ) ;
2013-03-04 20:26:48 +00:00
ChannelDummyRef & ref = mGenRefs [ idx ] ;
RsGxsGroupId grpId = ref . mGroupId ;
RsGxsMessageId parentId = ref . mMsgId ;
mGenThreadId = ref . mThreadId ;
2014-03-17 20:56:06 +00:00
if ( mGenThreadId . isNull ( ) )
2013-03-04 20:26:48 +00:00
{
mGenThreadId = parentId ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Generating Post ... " ;
2013-03-04 20:26:48 +00:00
std : : cerr < < " GroupId: " < < grpId ;
std : : cerr < < " ThreadId: " < < mGenThreadId ;
std : : cerr < < " ParentId: " < < parentId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
2013-03-13 00:24:57 +00:00
generatePost ( mGenToken , grpId ) ;
}
else if ( mGenCount < MAX_GEN_COMMENTS )
{
/* create a new post */
uint32_t idx = ( uint32_t ) ( ( mGenCount - MAX_GEN_GROUPS ) * RSRandom : : random_f32 ( ) ) ;
ChannelDummyRef & ref = mGenRefs [ idx + MAX_GEN_GROUPS ] ;
RsGxsGroupId grpId = ref . mGroupId ;
RsGxsMessageId parentId = ref . mMsgId ;
mGenThreadId = ref . mThreadId ;
2014-03-17 20:56:06 +00:00
if ( mGenThreadId . isNull ( ) )
2013-03-04 20:26:48 +00:00
{
2013-03-13 00:24:57 +00:00
mGenThreadId = parentId ;
2013-03-04 20:26:48 +00:00
}
2013-03-13 00:24:57 +00:00
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Generating Comment ... " ;
std : : cerr < < " GroupId: " < < grpId ;
std : : cerr < < " ThreadId: " < < mGenThreadId ;
std : : cerr < < " ParentId: " < < parentId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-13 00:24:57 +00:00
generateComment ( mGenToken , grpId , parentId , mGenThreadId ) ;
}
else
{
/* create a new post */
uint32_t idx = ( uint32_t ) ( ( MAX_GEN_COMMENTS - MAX_GEN_POSTS ) * RSRandom : : random_f32 ( ) ) ;
ChannelDummyRef & ref = mGenRefs [ idx + MAX_GEN_POSTS ] ;
RsGxsGroupId grpId = ref . mGroupId ;
RsGxsMessageId parentId = ref . mMsgId ;
mGenThreadId = ref . mThreadId ;
2014-03-17 20:56:06 +00:00
if ( mGenThreadId . isNull ( ) )
2013-03-04 20:26:48 +00:00
{
2013-03-13 00:24:57 +00:00
mGenThreadId = parentId ;
2013-03-04 20:26:48 +00:00
}
2013-03-13 00:24:57 +00:00
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::dummy_tick() Generating Vote ... " ;
std : : cerr < < " GroupId: " < < grpId ;
std : : cerr < < " ThreadId: " < < mGenThreadId ;
std : : cerr < < " ParentId: " < < parentId ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-13 00:24:57 +00:00
generateVote ( mGenToken , grpId , parentId , mGenThreadId ) ;
2013-03-04 20:26:48 +00:00
}
2013-03-13 00:24:57 +00:00
2013-03-04 20:26:48 +00:00
}
2018-08-16 23:34:29 +02:00
2020-06-16 21:13:55 +02:00
# ifdef TO_REMOVE
2018-11-01 07:04:01 +01:00
cleanTimedOutCallbacks ( ) ;
2020-06-16 21:13:55 +02:00
# endif
2013-03-04 20:26:48 +00:00
}
bool p3GxsChannels : : generatePost ( uint32_t & token , const RsGxsGroupId & grpId )
{
RsGxsChannelPost msg ;
std : : string rndId = genRandomId ( ) ;
rs_sprintf ( msg . mMsg , " Channel Msg: GroupId: %s, some randomness: %s " ,
2014-03-17 20:56:06 +00:00
grpId . toStdString ( ) . c_str ( ) , rndId . c_str ( ) ) ;
2013-03-04 20:26:48 +00:00
msg . mMeta . mMsgName = msg . mMsg ;
msg . mMeta . mGroupId = grpId ;
2014-04-20 16:34:26 +00:00
msg . mMeta . mThreadId . clear ( ) ;
msg . mMeta . mParentId . clear ( ) ;
2013-03-04 20:26:48 +00:00
2014-10-12 15:53:23 +00:00
msg . mMeta . mMsgStatus = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
2013-03-04 20:26:48 +00:00
createPost ( token , msg ) ;
return true ;
}
bool p3GxsChannels : : generateComment ( uint32_t & token , const RsGxsGroupId & grpId , const RsGxsMessageId & parentId , const RsGxsMessageId & threadId )
{
RsGxsComment msg ;
std : : string rndId = genRandomId ( ) ;
rs_sprintf ( msg . mComment , " Channel Comment: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s " ,
2014-03-17 20:56:06 +00:00
grpId . toStdString ( ) . c_str ( ) , threadId . toStdString ( ) . c_str ( ) , parentId . toStdString ( ) . c_str ( ) , rndId . c_str ( ) ) ;
2013-03-04 20:26:48 +00:00
msg . mMeta . mMsgName = msg . mComment ;
msg . mMeta . mGroupId = grpId ;
msg . mMeta . mThreadId = threadId ;
msg . mMeta . mParentId = parentId ;
2014-10-12 15:53:23 +00:00
msg . mMeta . mMsgStatus = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
2013-03-04 20:26:48 +00:00
/* chose a random Id to sign with */
std : : list < RsGxsId > ownIds ;
std : : list < RsGxsId > : : iterator it ;
rsIdentity - > getOwnIds ( ownIds ) ;
uint32_t idx = ( uint32_t ) ( ownIds . size ( ) * RSRandom : : random_f32 ( ) ) ;
2013-03-11 20:40:28 +00:00
uint32_t i = 0 ;
2014-10-24 22:07:26 +00:00
for ( it = ownIds . begin ( ) ; ( it ! = ownIds . end ( ) ) & & ( i < idx ) ; + + it , + + i ) ;
2013-03-04 20:26:48 +00:00
if ( it ! = ownIds . end ( ) )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::generateComment() Author: " < < * it ;
2013-03-04 20:26:48 +00:00
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
msg . mMeta . mAuthorId = * it ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
else
{
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::generateComment() No Author! " ;
2013-03-04 20:26:48 +00:00
std : : cerr < < std : : endl ;
}
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
2019-02-14 21:58:33 +01:00
createNewComment ( token , msg ) ;
2013-03-04 20:26:48 +00:00
return true ;
}
2013-03-13 00:24:57 +00:00
bool p3GxsChannels : : generateVote ( uint32_t & token , const RsGxsGroupId & grpId , const RsGxsMessageId & parentId , const RsGxsMessageId & threadId )
{
RsGxsVote vote ;
vote . mMeta . mGroupId = grpId ;
vote . mMeta . mThreadId = threadId ;
vote . mMeta . mParentId = parentId ;
2014-10-12 15:53:23 +00:00
vote . mMeta . mMsgStatus = GXS_SERV : : GXS_MSG_STATUS_UNPROCESSED ;
2013-03-13 00:24:57 +00:00
/* chose a random Id to sign with */
std : : list < RsGxsId > ownIds ;
std : : list < RsGxsId > : : iterator it ;
rsIdentity - > getOwnIds ( ownIds ) ;
uint32_t idx = ( uint32_t ) ( ownIds . size ( ) * RSRandom : : random_f32 ( ) ) ;
uint32_t i = 0 ;
2014-10-24 22:07:26 +00:00
for ( it = ownIds . begin ( ) ; ( it ! = ownIds . end ( ) ) & & ( i < idx ) ; + + it , + + i ) ;
2013-03-13 00:24:57 +00:00
if ( it ! = ownIds . end ( ) )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
std : : cerr < < " p3GxsChannels::generateVote() Author: " < < * it ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-13 00:24:57 +00:00
vote . mMeta . mAuthorId = * it ;
}
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-13 00:24:57 +00:00
else
{
std : : cerr < < " p3GxsChannels::generateVote() No Author! " ;
std : : cerr < < std : : endl ;
}
2014-12-21 19:12:40 +00:00
# endif
2013-03-13 00:24:57 +00:00
if ( 0.7 > RSRandom : : random_f32 ( ) )
{
// 70 % postive votes
vote . mVoteType = GXS_VOTE_UP ;
}
else
{
vote . mVoteType = GXS_VOTE_DOWN ;
}
2019-02-14 21:58:33 +01:00
createNewVote ( token , vote ) ;
2013-03-13 00:24:57 +00:00
return true ;
}
2013-03-04 20:26:48 +00:00
bool p3GxsChannels : : generateGroup ( uint32_t & token , std : : string groupName )
{
/* generate a new channel */
RsGxsChannelGroup channel ;
channel . mMeta . mGroupName = groupName ;
createGroup ( token , channel ) ;
return true ;
}
2013-03-16 12:31:31 +00:00
// Overloaded from RsTickEvent for Event callbacks.
2013-03-04 20:26:48 +00:00
void p3GxsChannels : : handle_event ( uint32_t event_type , const std : : string & elabel )
{
2014-12-21 19:12:40 +00:00
# ifdef GXSCHANNELS_DEBUG
2013-03-04 20:26:48 +00:00
std : : cerr < < " p3GxsChannels::handle_event( " < < event_type < < " ) " ;
std : : cerr < < std : : endl ;
2014-12-21 19:12:40 +00:00
# endif
2013-03-04 20:26:48 +00:00
// stuff.
switch ( event_type )
{
case CHANNEL_TESTEVENT_DUMMYDATA :
generateDummyData ( ) ;
break ;
2013-03-11 20:40:28 +00:00
case CHANNEL_PROCESS :
request_AllSubscribedGroups ( ) ;
2015-06-15 20:41:27 +00:00
break ;
2013-03-11 20:40:28 +00:00
2013-03-04 20:26:48 +00:00
default :
/* error */
2016-02-08 19:42:56 +01:00
std : : cerr < < " p3GxsChannels::handle_event() Unknown Event Type: " < < event_type < < " elabel: " < < elabel ;
2013-03-04 20:26:48 +00:00
std : : cerr < < std : : endl ;
break ;
}
}
2018-06-13 22:46:27 +02:00
TurtleRequestId p3GxsChannels : : turtleGroupRequest ( const RsGxsGroupId & group_id )
2018-06-06 23:15:29 +02:00
{
2018-06-13 22:46:27 +02:00
return netService ( ) - > turtleGroupRequest ( group_id ) ;
2018-06-06 23:15:29 +02:00
}
2018-06-13 22:46:27 +02:00
TurtleRequestId p3GxsChannels : : turtleSearchRequest ( const std : : string & match_string )
2018-06-06 23:15:29 +02:00
{
2018-11-01 07:04:01 +01:00
return netService ( ) - > turtleSearchRequest ( match_string ) ;
2018-06-06 23:15:29 +02:00
}
2018-06-24 16:55:38 +02:00
bool p3GxsChannels : : clearDistantSearchResults ( TurtleRequestId req )
{
return netService ( ) - > clearDistantSearchResults ( req ) ;
}
2020-06-16 21:13:55 +02:00
bool p3GxsChannels : : retrieveDistantSearchResults ( TurtleRequestId req , std : : map < RsGxsGroupId , RsGxsGroupSearchResults > & results )
2018-06-24 16:55:38 +02:00
{
return netService ( ) - > retrieveDistantSearchResults ( req , results ) ;
}
2020-10-25 22:47:48 +01:00
DistantSearchGroupStatus p3GxsChannels : : getDistantSearchStatus ( const RsGxsGroupId & group_id )
{
return netService ( ) - > getDistantSearchStatus ( group_id ) ;
}
2020-06-25 21:15:37 +02:00
bool p3GxsChannels : : getDistantSearchResultGroupData ( const RsGxsGroupId & group_id , RsGxsChannelGroup & distant_group )
2018-06-26 22:20:02 +02:00
{
2020-06-16 21:13:55 +02:00
RsGxsGroupSearchResults gs ;
2018-06-26 22:20:02 +02:00
if ( netService ( ) - > retrieveDistantGroupSummary ( group_id , gs ) )
{
2020-06-16 21:13:55 +02:00
// This is a placeholder information by the time we receive the full group meta data and check the signature.
2018-07-22 21:33:40 +02:00
distant_group . mMeta . mGroupId = gs . mGroupId ;
distant_group . mMeta . mGroupName = gs . mGroupName ;
2018-06-26 22:20:02 +02:00
distant_group . mMeta . mGroupFlags = GXS_SERV : : FLAG_PRIVACY_PUBLIC ;
2018-07-22 21:33:40 +02:00
distant_group . mMeta . mSignFlags = gs . mSignFlags ;
2018-06-26 22:20:02 +02:00
2018-07-22 21:33:40 +02:00
distant_group . mMeta . mPublishTs = gs . mPublishTs ;
distant_group . mMeta . mAuthorId = gs . mAuthorId ;
2018-06-26 22:20:02 +02:00
distant_group . mMeta . mCircleType = GXS_CIRCLE_TYPE_PUBLIC ; // guessed, otherwise the group would not be search-able.
// other stuff.
distant_group . mMeta . mAuthenFlags = 0 ; // wild guess...
distant_group . mMeta . mSubscribeFlags = GXS_SERV : : GROUP_SUBSCRIBE_NOT_SUBSCRIBED ;
2018-07-22 21:33:40 +02:00
distant_group . mMeta . mPop = gs . mPopularity ; // Popularity = number of friend subscribers
distant_group . mMeta . mVisibleMsgCount = gs . mNumberOfMessages ; // Max messages reported by friends
distant_group . mMeta . mLastPost = gs . mLastMessageTs ; // Timestamp for last message. Not used yet.
2018-06-26 22:20:02 +02:00
return true ;
}
else
return false ;
}
2020-06-16 21:13:55 +02:00
# ifdef TO_REMOVE
2018-08-16 23:34:29 +02:00
bool p3GxsChannels : : turtleSearchRequest (
const std : : string & matchString ,
const std : : function < void ( const RsGxsGroupSummary & ) > & multiCallback ,
2018-10-07 01:34:05 +02:00
rstime_t maxWait )
2018-08-16 23:34:29 +02:00
{
if ( matchString . empty ( ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " match string can't be empty! "
< < std : : endl ;
return false ;
}
TurtleRequestId sId = turtleSearchRequest ( matchString ) ;
2018-11-01 07:04:01 +01:00
{
2018-08-16 23:34:29 +02:00
RS_STACK_MUTEX ( mSearchCallbacksMapMutex ) ;
mSearchCallbacksMap . emplace (
sId ,
std : : make_pair (
multiCallback ,
std : : chrono : : system_clock : : now ( ) +
2018-11-01 07:04:01 +01:00
std : : chrono : : seconds ( maxWait ) ) ) ;
}
return true ;
}
/// @see RsGxsChannels::turtleChannelRequest
bool p3GxsChannels : : turtleChannelRequest (
const RsGxsGroupId & channelId ,
const std : : function < void ( const RsGxsChannelGroup & result ) > & multiCallback ,
rstime_t maxWait )
{
if ( channelId . isNull ( ) )
{
2019-04-05 01:43:23 +02:00
std : : cerr < < __PRETTY_FUNCTION__ < < " Error! channelId can't be null! "
2018-11-01 07:04:01 +01:00
< < std : : endl ;
return false ;
}
TurtleRequestId sId = turtleGroupRequest ( channelId ) ;
{
RS_STACK_MUTEX ( mDistantChannelsCallbacksMapMutex ) ;
mDistantChannelsCallbacksMap . emplace (
sId ,
std : : make_pair (
multiCallback ,
std : : chrono : : system_clock : : now ( ) +
std : : chrono : : seconds ( maxWait ) ) ) ;
}
2018-08-16 23:34:29 +02:00
return true ;
}
2018-06-24 16:55:38 +02:00
2018-11-17 17:19:13 +01:00
/// @see RsGxsChannels::localSearchRequest
bool p3GxsChannels : : localSearchRequest (
const std : : string & matchString ,
const std : : function < void ( const RsGxsGroupSummary & result ) > & multiCallback ,
rstime_t maxWait )
{
if ( matchString . empty ( ) )
{
std : : cerr < < __PRETTY_FUNCTION__ < < " match string can't be empty! "
< < std : : endl ;
return false ;
}
auto timeout = std : : chrono : : steady_clock : : now ( ) + std : : chrono : : seconds ( maxWait ) ;
RsThread : : async ( [ = ] ( )
{
std : : list < RsGxsGroupSummary > results ;
RsGenExchange : : localSearch ( matchString , results ) ;
if ( std : : chrono : : steady_clock : : now ( ) < timeout )
for ( const RsGxsGroupSummary & result : results ) multiCallback ( result ) ;
} ) ;
return true ;
}
2020-06-16 21:13:55 +02:00
# endif
2018-11-17 17:19:13 +01:00
2020-06-16 21:13:55 +02:00
void p3GxsChannels : : receiveDistantSearchResults ( TurtleRequestId id , const RsGxsGroupId & grpId )
2018-08-16 23:34:29 +02:00
{
2020-06-16 21:13:55 +02:00
if ( ! rsEvents )
return ;
// We temporise here, in order to avoid notifying clients with many events
// So we put some data in there and will send an event with all of them at once every 1 sec at most.
mSearchResultsToNotify [ id ] . insert ( grpId ) ;
2018-08-16 23:34:29 +02:00
}
2021-02-06 17:31:43 +01:00
bool p3GxsChannels : : exportChannelLink ( std : : string & link , const RsGxsGroupId & chanId , bool includeGxsData , const std : : string & baseUrl , std : : string & errMsg )
2019-10-28 18:45:50 +01:00
{
constexpr auto fname = __PRETTY_FUNCTION__ ;
const auto failure = [ & ] ( const std : : string & err )
{
errMsg = err ;
RsErr ( ) < < fname < < " " < < err < < std : : endl ;
return false ;
} ;
if ( chanId . isNull ( ) ) return failure ( " chanId 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 , chanId , errMsg ) )
return failure ( errMsg ) ;
if ( outputRadix ) return true ;
std : : vector < RsGxsChannelGroup > chansInfo ;
if ( ! getChannelsInfo ( std : : list < RsGxsGroupId > ( { chanId } ) , chansInfo )
| | chansInfo . empty ( ) )
return failure ( " failure retrieving channel information " ) ;
RsUrl inviteUrl ( baseUrl ) ;
inviteUrl . setQueryKV ( CHANNEL_URL_ID_FIELD , chanId . toStdString ( ) ) ;
inviteUrl . setQueryKV ( CHANNEL_URL_NAME_FIELD , chansInfo [ 0 ] . mMeta . mGroupName ) ;
if ( includeGxsData ) inviteUrl . setQueryKV ( CHANNEL_URL_DATA_FIELD , link ) ;
link = inviteUrl . toString ( ) ;
return true ;
}
2021-02-06 17:31:43 +01:00
bool p3GxsChannels : : importChannelLink ( const std : : string & link , RsGxsGroupId & chanId , std : : string & errMsg )
2019-10-28 18:45:50 +01:00
{
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 ( CHANNEL_URL_DATA_FIELD ) ;
if ( qIt ! = query . end ( ) ) radixPtr = & qIt - > second ;
if ( radixPtr - > empty ( ) ) return failure ( CHANNEL_URL_DATA_FIELD + " is empty " ) ;
if ( ! RsGenExchange : : importGroupBase64 ( * radixPtr , chanId , errMsg ) )
return failure ( errMsg ) ;
return true ;
}
2021-02-06 17:31:43 +01:00
/*static*/ const std : : string RsGxsChannels : : DEFAULT_CHANNEL_BASE_URL = " retroshare:///channels " ;
/*static*/ const std : : string RsGxsChannels : : CHANNEL_URL_NAME_FIELD = " chanName " ;
/*static*/ const std : : string RsGxsChannels : : CHANNEL_URL_ID_FIELD = " chanId " ;
/*static*/ const std : : string RsGxsChannels : : CHANNEL_URL_DATA_FIELD = " chanData " ;
/*static*/ const std : : string RsGxsChannels : : CHANNEL_URL_MSG_TITLE_FIELD = " chanMsgTitle " ;
/*static*/ const std : : string RsGxsChannels : : CHANNEL_URL_MSG_ID_FIELD = " chanMsgId " ;
2019-10-28 18:45:50 +01:00
2019-09-19 16:26:43 +02:00
RsGxsChannelGroup : : ~ RsGxsChannelGroup ( ) = default ;
RsGxsChannelPost : : ~ RsGxsChannelPost ( ) = default ;
2019-09-27 16:21:08 +02:00
RsGxsChannels : : ~ RsGxsChannels ( ) = default ;