diff --git a/.pubnub.yml b/.pubnub.yml index 960f5650..12685d14 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,8 +1,17 @@ name: c-core schema: 1 -version: "4.11.2" +version: "4.12.0" scm: github.com/pubnub/c-core changelog: + - date: 2024-07-29 + version: v4.12.0 + changes: + - type: feature + text: "Added `filter` and `sort` parameters to be closer to the other SDKs with object API." + - type: feature + text: "Configurable `bool` type." + - type: bug + text: "Missing features needed for grant token API in CMakeLIsts.txt." - date: 2024-07-15 version: v4.11.2 changes: @@ -819,7 +828,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" @@ -885,7 +894,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" @@ -951,7 +960,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" @@ -1013,7 +1022,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" @@ -1074,7 +1083,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" @@ -1130,7 +1139,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" @@ -1183,7 +1192,7 @@ sdks: distribution-type: source code distribution-repository: GitHub release package-name: C-Core - location: https://github.com/pubnub/c-core/releases/tag/v4.11.2 + location: https://github.com/pubnub/c-core/releases/tag/v4.12.0 requires: - name: "miniz" diff --git a/CHANGELOG.md b/CHANGELOG.md index de74cc3c..e20502db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v4.12.0 +July 29 2024 + +#### Added +- Added `filter` and `sort` parameters to be closer to the other SDKs with object API. +- Configurable `bool` type. + +#### Fixed +- Missing features needed for grant token API in CMakeLIsts.txt. + ## v4.11.2 July 15 2024 diff --git a/CMakeLists.txt b/CMakeLists.txt index c5b088fe..ca87fe46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ log_set(CUSTOM_OPENSSL_INCLUDE_DIR "include" "OpenSSL include directory relative log_set(EXAMPLE "all" "Build example with provided name (use 'all' for all examples) [EXAMPLES=ON needed]") log_set(CGREEN_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/cgreen" "CGreen root directory [UNIT_TEST=ON needed]") log_set(LOG_LEVEL "WARNING" "Log level [TRACE/DEBUG/INFO/WARNING/ERROR]") +log_set(CUSTOM_BOOL_TYPE "" "Type of bool for platform differences. Select whatever works for you that accepts 0/1 values") if (${OPENSSL} AND ${MBEDTLS}) message(FATAL_ERROR "You can't use both OpenSSL and mbedTLS at the same time!") @@ -143,6 +144,13 @@ if(${WITH_CPP}) endif() endif() +if(NOT ${CUSTOM_BOOL_TYPE} STREQUAL "") + message(STATUS "Using custom bool type: ${BOOL_TYPE}") + set(FLAGS "\ + ${FLAGS} \ + -D PUBNUB_BOOL_TYPE=${BOOL_TYPE}") +endif() + set(CORE_SOURCEFILES ${CMAKE_CURRENT_LIST_DIR}/core/pbcc_set_state.c ${CMAKE_CURRENT_LIST_DIR}/core/pubnub_pubsubapi.c @@ -372,6 +380,9 @@ endif() if(${USE_GRANT_TOKEN_API}) set(FEATURE_SOURCEFILES ${FEATURE_SOURCEFILES} + ${CMAKE_CURRENT_LIST_DIR}/lib/cbor/cborparser.c + ${CMAKE_CURRENT_LIST_DIR}/lib/cbor/cborerrorstrings.c + ${CMAKE_CURRENT_LIST_DIR}/lib/cbor/cborparser_dup_string.c ${CMAKE_CURRENT_LIST_DIR}/core/pbcc_grant_token_api.c ${CMAKE_CURRENT_LIST_DIR}/core/pubnub_grant_token_api.c) endif() @@ -673,6 +684,16 @@ if(${EXAMPLES}) set(EXAMPLE_LIST pubnub_crypto_module_sample ${EXAMPLE_LIST}) + if (${USE_GRANT_TOKEN_API}) + set(EXAMPLE_LIST + pubnub_sync_grant_token_sample + ${EXAMPLE_LIST}) + endif() + endif() + if (${USE_OBJECTS_API}) + set(EXAMPLE_LIST + pubnub_objects_api_sample + ${EXAMPLE_LIST}) endif() endif() else() diff --git a/core/c99/stdbool.h b/core/c99/stdbool.h index c9c7ce3e..ad6ed99f 100644 --- a/core/c99/stdbool.h +++ b/core/c99/stdbool.h @@ -5,6 +5,10 @@ #define false 0 #define true 1 +#ifdef PUBNUB_BOOL_TYPE +#define bool PUBNUB_BOOL_TYPE +#else #define bool int +#endif -#endif /* !defined __cplusplus */ \ No newline at end of file +#endif /* !defined __cplusplus */ diff --git a/core/pbcc_objects_api.c b/core/pbcc_objects_api.c index 68f64c31..c81d61b4 100644 --- a/core/pbcc_objects_api.c +++ b/core/pbcc_objects_api.c @@ -77,6 +77,8 @@ enum pubnub_res pbcc_getall_uuidmetadata_prep( char const* start, char const* end, enum pubnub_tribool count, + char const* filter, + char const* sort, enum pubnub_trans pt) { char const* const uname = pubnub_uname(); @@ -102,6 +104,9 @@ enum pubnub_res pbcc_getall_uuidmetadata_prep( if (count != pbccNotSet) { ADD_URL_PARAM(qparam, count, count == pbccTrue ? "true" : "false"); } + if (NULL != filter) { ADD_URL_PARAM(qparam, filter, filter); } + if (NULL != sort) { ADD_URL_PARAM(qparam, sort, sort); } + if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } @@ -292,6 +297,8 @@ enum pubnub_res pbcc_getall_channelmetadata_prep(struct pbcc_context* pb, char const* start, char const* end, enum pubnub_tribool count, + char const* filter, + char const* sort, enum pubnub_trans pt) { char const* const uname = pubnub_uname(); @@ -316,6 +323,10 @@ enum pubnub_res pbcc_getall_channelmetadata_prep(struct pbcc_context* pb, if (end != NULL) { ADD_URL_PARAM(qparam, end, end); } if (count != pbccNotSet) { ADD_URL_PARAM(qparam, count, count == pbccTrue ? "true" : "false"); } + + if (NULL != filter) { ADD_URL_PARAM(qparam, filter, filter); } + if (NULL != sort) { ADD_URL_PARAM(qparam, sort, sort); } + if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } @@ -515,6 +526,8 @@ enum pubnub_res pbcc_get_memberships_prep(struct pbcc_context* pb, char const* start, char const* end, enum pubnub_tribool count, + char const* filter, + char const* sort, enum pubnub_trans pt) { char const* const uname = pubnub_uname(); @@ -542,6 +555,10 @@ enum pubnub_res pbcc_get_memberships_prep(struct pbcc_context* pb, if (start) { ADD_URL_PARAM(qparam, start, start); } if (end) { ADD_URL_PARAM(qparam, end, end); } if (count != pbccNotSet) { ADD_URL_PARAM(qparam, count, count == pbccTrue ? "true" : "false"); } + + if (NULL != filter) { ADD_URL_PARAM(qparam, filter, filter); } + if (NULL != sort) { ADD_URL_PARAM(qparam, sort, sort); } + if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } @@ -574,6 +591,12 @@ enum pubnub_res pbcc_set_memberships_prep(struct pbcc_context* pb, char const* uuid_metadataid, char const* include, char const* set_obj, + char const* filter, + char const* sort, + size_t limit, + char const* start, + char const* end, + enum pubnub_tribool count, enum pubnub_trans pt) { char const* const uname = pubnub_uname(); @@ -598,6 +621,16 @@ enum pubnub_res pbcc_set_memberships_prep(struct pbcc_context* pb, URL_PARAMS_INIT(qparam, PUBNUB_MAX_URL_PARAMS); if (uname) { ADD_URL_PARAM(qparam, pnsdk, uname); } if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } + + if (limit > 0) { ADD_URL_PARAM_SIZET(qparam, limit, limit); } + if (NULL != start) { ADD_URL_PARAM(qparam, start, start); } + if (NULL != end) { ADD_URL_PARAM(qparam, end, end); } + + if (count != pbccNotSet) { ADD_URL_PARAM(qparam, count, count == pbccTrue ? "true" : "false"); } + + if (NULL != filter) { ADD_URL_PARAM(qparam, filter, filter); } + if (NULL != sort) { ADD_URL_PARAM(qparam, sort, sort); } + #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } ADD_TS_TO_URL_PARAM(); @@ -633,6 +666,8 @@ enum pubnub_res pbcc_get_members_prep(struct pbcc_context* pb, size_t limit, char const* start, char const* end, + char const* filter, + char const* sort, enum pubnub_tribool count, enum pubnub_trans pt) { @@ -663,6 +698,10 @@ enum pubnub_res pbcc_get_members_prep(struct pbcc_context* pb, if (start) { ADD_URL_PARAM(qparam, start, start); } if (end) { ADD_URL_PARAM(qparam, end, end); } if (count != pbccNotSet) { ADD_URL_PARAM(qparam, count, count == pbccTrue ? "true" : "false"); } + + if (NULL != filter) { ADD_URL_PARAM(qparam, filter, filter); } + if (NULL != sort) { ADD_URL_PARAM(qparam, sort, sort); } + if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } @@ -695,6 +734,12 @@ enum pubnub_res pbcc_set_members_prep(struct pbcc_context* pb, char const* channel_metadataid, char const* include, char const* set_obj, + char const* filter, + char const* sort, + size_t limit, + char const* start, + char const* end, + enum pubnub_tribool count, enum pubnub_trans pt) { char const* const uname = pubnub_uname(); @@ -720,6 +765,15 @@ enum pubnub_res pbcc_set_members_prep(struct pbcc_context* pb, URL_PARAMS_INIT(qparam, PUBNUB_MAX_URL_PARAMS); if (uname) { ADD_URL_PARAM(qparam, pnsdk, uname); } if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } + + if (limit > 0) { ADD_URL_PARAM_SIZET(qparam, limit, limit); } + if (NULL != start) { ADD_URL_PARAM(qparam, start, start); } + if (NULL != end) { ADD_URL_PARAM(qparam, end, end); } + + if (count != pbccNotSet) { ADD_URL_PARAM(qparam, count, count == pbccTrue ? "true" : "false"); } + + if (NULL != filter) { ADD_URL_PARAM(qparam, filter, filter); } + if (NULL != sort) { ADD_URL_PARAM(qparam, sort, sort); } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } ADD_TS_TO_URL_PARAM(); diff --git a/core/pbcc_objects_api.h b/core/pbcc_objects_api.h index 55579285..ab64f024 100644 --- a/core/pbcc_objects_api.h +++ b/core/pbcc_objects_api.h @@ -26,6 +26,8 @@ enum pubnub_res pbcc_find_objects_id(struct pbcc_context* pb, char const* file, int line); +// TODO: maybe we should decrease amount of parameters in these functions + /** Prepares the 'get_users' transaction, mostly by formatting the URI of the HTTP request. */ @@ -35,6 +37,8 @@ enum pubnub_res pbcc_getall_uuidmetadata_prep(struct pbcc_context* pb, char const* start, char const* end, enum pubnub_tribool count, + char const* filter, + char const* sort, enum pubnub_trans pt); /** Prepares the 'set_uuidmetadata' transaction, mostly by @@ -70,6 +74,8 @@ enum pubnub_res pbcc_getall_channelmetadata_prep(struct pbcc_context* pb, char const* start, char const* end, enum pubnub_tribool count, + char const* filter, + char const* sort, enum pubnub_trans pt); @@ -108,6 +114,8 @@ enum pubnub_res pbcc_get_memberships_prep(struct pbcc_context* pb, char const* start, char const* end, enum pubnub_tribool count, + char const* filter, + char const* sort, enum pubnub_trans pt); @@ -118,6 +126,12 @@ enum pubnub_res pbcc_set_memberships_prep(struct pbcc_context* pb, char const* uuid_metadataid, char const* include, char const* update_obj, + char const* filter, + char const* sort, + size_t limit, + char const* start, + char const* end, + enum pubnub_tribool count, enum pubnub_trans pt); /** Prepares the 'get_members' transaction, mostly by @@ -129,6 +143,8 @@ enum pubnub_res pbcc_get_members_prep(struct pbcc_context* pb, size_t limit, char const* start, char const* end, + char const* filter, + char const* sort, enum pubnub_tribool count, enum pubnub_trans pt); @@ -139,6 +155,12 @@ enum pubnub_res pbcc_set_members_prep(struct pbcc_context* pb, char const* channel_metadataid, char const* include, char const* set_obj, + char const* filter, + char const* sort, + size_t limit, + char const* start, + char const* end, + enum pubnub_tribool count, enum pubnub_trans pt); diff --git a/core/pubnub_objects_api.c b/core/pubnub_objects_api.c index 6d87d93d..7c00af7d 100644 --- a/core/pubnub_objects_api.c +++ b/core/pubnub_objects_api.c @@ -38,6 +38,26 @@ do { json = (obj_buffer); \ } while(0) +const struct pubnub_page_object pubnub_null_page = {NULL, NULL}; + +const struct pubnub_user_data pubnub_null_user_data = {NULL, NULL, NULL, NULL, NULL}; + +const struct pubnub_channel_data pubnub_null_channel_data = {NULL, NULL, NULL}; + + +struct pubnub_getall_metadata_opts pubnub_getall_metadata_defopts(void) +{ + struct pubnub_getall_metadata_opts opts; + opts.include = NULL; + opts.filter = NULL; + opts.sort = NULL; + opts.limit = 100; + opts.count = pbccNotSet; + opts.page = pubnub_null_page; + + return opts; +} + enum pubnub_res pubnub_getall_uuidmetadata(pubnub_t* pb, char const* include, @@ -45,6 +65,19 @@ enum pubnub_res pubnub_getall_uuidmetadata(pubnub_t* pb, char const* start, char const* end, enum pubnub_tribool count) +{ + struct pubnub_getall_metadata_opts opts = pubnub_getall_metadata_defopts(); + opts.include = include; + opts.limit = limit; + opts.page.next = start; + opts.page.prev = end; + opts.count = count; + + return pubnub_getall_uuidmetadata_ex(pb, opts); +} + + +enum pubnub_res pubnub_getall_uuidmetadata_ex(pubnub_t* pb, struct pubnub_getall_metadata_opts opts) { enum pubnub_res rslt; @@ -57,11 +90,13 @@ enum pubnub_res pubnub_getall_uuidmetadata(pubnub_t* pb, } pb->trans = PBTT_GETALL_UUIDMETADATA; rslt = pbcc_getall_uuidmetadata_prep(&pb->core, - include, - limit, - start, - end, - count, + opts.include, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, + opts.filter, + opts.sort, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_GETALL_UUIDMETADATA; @@ -75,6 +110,17 @@ enum pubnub_res pubnub_getall_uuidmetadata(pubnub_t* pb, } +struct pubnub_set_uuidmetadata_opts pubnub_set_uuidmetadata_defopts(void) +{ + struct pubnub_set_uuidmetadata_opts opts; + opts.uuid = NULL; + opts.include = NULL; + opts.data = pubnub_null_user_data; + + return opts; +} + + enum pubnub_res pubnub_set_uuidmetadata(pubnub_t* pb, char const* uuid_metadataid, char const* include, @@ -92,7 +138,11 @@ enum pubnub_res pubnub_set_uuidmetadata(pubnub_t* pb, pb->method = pubnubUsePATCH; pb->trans = PBTT_SET_UUIDMETADATA; - rslt = pbcc_set_uuidmetadata_prep(&pb->core, uuid_metadataid, include, uuid_metadata_obj, pb->trans); + rslt = pbcc_set_uuidmetadata_prep(&pb->core, + uuid_metadataid, + include, + uuid_metadata_obj, + pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_SET_UUIDMETADATA; pb->core.last_result = PNR_STARTED; @@ -106,6 +156,71 @@ enum pubnub_res pubnub_set_uuidmetadata(pubnub_t* pb, } +enum pubnub_res pubnub_set_uuidmetadata_ex(pubnub_t* pb, + struct pubnub_set_uuidmetadata_opts opts) +{ + char* obj_buffer = NULL; + enum pubnub_res result; + size_t obj_len = 0; + + obj_len = NULL != opts.data.custom ? strlen(opts.data.custom) : 0; + obj_len += NULL != opts.data.email ? strlen(opts.data.email) : 0; + obj_len += NULL != opts.data.name ? strlen(opts.data.name) : 0; + obj_len += NULL != opts.data.external_id ? strlen(opts.data.external_id) : 0; + obj_len += NULL != opts.data.profile_url ? strlen(opts.data.profile_url) : 0; + + obj_buffer = (char*)malloc(obj_len + 64); // 64 is for the JSON object structure with small buffer + int offset = snprintf(obj_buffer, obj_len, "{"); + + // TODO: maybe it will be a good idea to add serialization at some point to this SDK + if (NULL != opts.data.custom) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "\"custom\":%s", + opts.data.custom); + } + + if (NULL != opts.data.email) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "%s\"email\":\"%s\"", + offset > 1 ? "," : "", + opts.data.email); + } + + if (NULL != opts.data.name) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "%s\"name\":\"%s\"", + offset > 1 ? "," : "", + opts.data.name); + } + + if (NULL != opts.data.external_id) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "%s\"externalId\":\"%s\"", + offset > 1 ? "," : "", + opts.data.external_id); + } + + if (NULL != opts.data.profile_url) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "%s\"profileUrl\":\"%s\"", + offset > 1 ? "," : "", + opts.data.profile_url); + } + snprintf(obj_buffer + offset, obj_len - offset, "}\0"); + + result = pubnub_set_uuidmetadata(pb, opts.uuid, opts.include, obj_buffer); + free(obj_buffer); + + return result; +} + + + enum pubnub_res pubnub_get_uuidmetadata(pubnub_t* pb, char const* include, char const* uuid_metadataid) @@ -166,6 +281,20 @@ enum pubnub_res pubnub_getall_channelmetadata(pubnub_t* pb, char const* start, char const* end, enum pubnub_tribool count) +{ + struct pubnub_getall_metadata_opts opts = pubnub_getall_metadata_defopts(); + opts.include = include; + opts.limit = limit; + opts.page.next = start; + opts.page.prev = end; + opts.count = count; + + return pubnub_getall_channelmetadata_ex(pb, opts); +} + + +enum pubnub_res pubnub_getall_channelmetadata_ex(pubnub_t* pb, + struct pubnub_getall_metadata_opts opts) { enum pubnub_res rslt; @@ -178,11 +307,13 @@ enum pubnub_res pubnub_getall_channelmetadata(pubnub_t* pb, } pb->trans = PBTT_GETALL_CHANNELMETADATA; rslt = pbcc_getall_channelmetadata_prep(&pb->core, - include, - limit, - start, - end, - count, + opts.include, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, + opts.filter, + opts.sort, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_GETALL_CHANNELMETADATA; @@ -196,6 +327,16 @@ enum pubnub_res pubnub_getall_channelmetadata(pubnub_t* pb, } +struct pubnub_set_channelmetadata_opts pubnub_set_channelmetadata_defopts(void) +{ + struct pubnub_set_channelmetadata_opts opts; + opts.include = NULL; + opts.data = pubnub_null_channel_data; + + return opts; +} + + enum pubnub_res pubnub_set_channelmetadata(pubnub_t* pb, char const* channel_metadataid, char const* include, @@ -213,7 +354,11 @@ enum pubnub_res pubnub_set_channelmetadata(pubnub_t* pb, pb->method = pubnubUsePATCH; pb->trans = PBTT_SET_CHANNELMETADATA; - rslt = pbcc_set_channelmetadata_prep(&pb->core, channel_metadataid, include, channel_metadata_obj, pb->trans); + rslt = pbcc_set_channelmetadata_prep(&pb->core, + channel_metadataid, + include, + channel_metadata_obj, + pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_SET_CHANNELMETADATA; pb->core.last_result = PNR_STARTED; @@ -227,6 +372,50 @@ enum pubnub_res pubnub_set_channelmetadata(pubnub_t* pb, } +enum pubnub_res pubnub_set_channelmetadata_ex(pubnub_t* pb, + char const* channel, + struct pubnub_set_channelmetadata_opts opts) +{ + char* obj_buffer = NULL; + enum pubnub_res result; + size_t obj_len = 0; + + obj_len = NULL != opts.data.custom ? strlen(opts.data.custom) : 0; + obj_len += NULL != opts.data.description ? strlen(opts.data.description) : 0; + obj_len += NULL != opts.data.name ? strlen(opts.data.name) : 0; + + obj_buffer = (char*)malloc(obj_len + 64); // 64 is for the JSON object structure with small buffer + int offset = snprintf(obj_buffer, obj_len, "{"); + + if (NULL != opts.data.custom) { + offset += snprintf(obj_buffer, obj_len, "\"custom\":%s", opts.data.custom); + } + + if (NULL != opts.data.description) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "%s\"description\":\"%s\"", + offset > 1 ? "," : "", + opts.data.description); + } + + if (NULL != opts.data.name) { + offset += snprintf(obj_buffer + offset, + obj_len - offset, + "%s\"name\":\"%s\"", + offset > 1 ? "," : "", + opts.data.name); + } + + offset += snprintf(obj_buffer + offset, obj_len - offset, "}\0"); + + result = pubnub_set_channelmetadata(pb, channel, opts.include, obj_buffer); + free(obj_buffer); + + return result; +} + + enum pubnub_res pubnub_get_channelmetadata(pubnub_t* pb, char const* include, char const* channel_metadataid) @@ -282,6 +471,20 @@ enum pubnub_res pubnub_remove_channelmetadata(pubnub_t* pb, char const* channel_ } +struct pubnub_membership_opts pubnub_memberships_defopts(void) +{ + struct pubnub_membership_opts opts; + opts.uuid = NULL; + opts.include = NULL; + opts.page = pubnub_null_page; + opts.filter = NULL; + opts.sort = NULL; + opts.limit = 100; + + return opts; +} + + enum pubnub_res pubnub_get_memberships(pubnub_t* pb, char const* uuid_metadataid, char const* include, @@ -289,9 +492,28 @@ enum pubnub_res pubnub_get_memberships(pubnub_t* pb, char const* start, char const* end, enum pubnub_tribool count) +{ + struct pubnub_membership_opts opts = pubnub_memberships_defopts(); + opts.uuid = uuid_metadataid; + opts.include = include; + opts.limit = limit; + opts.page.next = start; + opts.page.prev = end; + opts.count = count; + + return pubnub_get_memberships_ex(pb, opts); +} + + +enum pubnub_res pubnub_get_memberships_ex(pubnub_t* pb, + struct pubnub_membership_opts opts) { enum pubnub_res rslt; + if (NULL == opts.uuid) { + opts.uuid = pb->core.user_id; + } + PUBNUB_ASSERT(pb_valid_ctx_ptr(pb)); pubnub_mutex_lock(pb->monitor); @@ -301,12 +523,14 @@ enum pubnub_res pubnub_get_memberships(pubnub_t* pb, } pb->trans = PBTT_GET_MEMBERSHIPS; rslt = pbcc_get_memberships_prep(&pb->core, - uuid_metadataid, - include, - limit, - start, - end, - count, + opts.uuid, + opts.include, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, + opts.filter, + opts.sort, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_GET_MEMBERSHIPS; @@ -324,6 +548,18 @@ enum pubnub_res pubnub_set_memberships(pubnub_t* pb, char const* uuid_metadataid, char const* include, char const* set_obj) +{ + struct pubnub_membership_opts opts = pubnub_memberships_defopts(); + opts.uuid = uuid_metadataid; + opts.include = include; + + return pubnub_set_memberships_ex(pb, set_obj, opts); +} + + +enum pubnub_res pubnub_set_memberships_ex(pubnub_t* pb, + char const* channels, + struct pubnub_membership_opts opts) { enum pubnub_res rslt; char obj_buffer[PUBNUB_BUF_MAXLEN]; @@ -341,14 +577,20 @@ enum pubnub_res pubnub_set_memberships(pubnub_t* pb, "pubnub_set_memberships", obj_buffer, "{\"set\":", - set_obj); + channels); pb->method = pubnubUsePATCH; pb->trans = PBTT_SET_MEMBERSHIPS; rslt = pbcc_set_memberships_prep(&pb->core, - uuid_metadataid, - include, - set_obj, + opts.uuid, + opts.include, + channels, + opts.filter, + opts.sort, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_SET_MEMBERSHIPS; @@ -367,9 +609,25 @@ enum pubnub_res pubnub_remove_memberships(pubnub_t* pb, char const* uuid_metadataid, char const* include, char const* remove_obj) +{ + struct pubnub_membership_opts opts = pubnub_memberships_defopts(); + opts.uuid = uuid_metadataid; + opts.include = include; + + return pubnub_remove_memberships_ex(pb, remove_obj, opts); +} + + +enum pubnub_res pubnub_remove_memberships_ex(pubnub_t* pb, + char const* channels, + struct pubnub_membership_opts opts) { enum pubnub_res rslt; char obj_buffer[PUBNUB_BUF_MAXLEN]; + + if (NULL == opts.uuid) { + opts.uuid = pb->core.user_id; + } PUBNUB_ASSERT(pb_valid_ctx_ptr(pb)); @@ -384,13 +642,19 @@ enum pubnub_res pubnub_remove_memberships(pubnub_t* pb, "pubnub_remove_memberships", obj_buffer, "{\"delete\":", - remove_obj); + channels); pb->method = pubnubUsePATCH; pb->trans = PBTT_REMOVE_MEMBERSHIPS; rslt = pbcc_set_memberships_prep(&pb->core, - uuid_metadataid, - include, - remove_obj, + opts.uuid, + opts.include, + channels, + opts.filter, + opts.sort, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_REMOVE_MEMBERSHIPS; @@ -405,6 +669,20 @@ enum pubnub_res pubnub_remove_memberships(pubnub_t* pb, } +struct pubnub_members_opts pubnub_members_defopts(void) +{ + struct pubnub_members_opts opts; + opts.include = NULL; + opts.filter = NULL; + opts.sort = NULL; + opts.limit = 100; + opts.page = pubnub_null_page; + opts.count = pbccNotSet; + + return opts; +} + + enum pubnub_res pubnub_get_members(pubnub_t* pb, char const* channel_metadataid, char const* include, @@ -412,6 +690,21 @@ enum pubnub_res pubnub_get_members(pubnub_t* pb, char const* start, char const* end, enum pubnub_tribool count) +{ + struct pubnub_members_opts opts = pubnub_members_defopts(); + opts.include = include; + opts.limit = limit; + opts.page.next = start; + opts.page.prev = end; + opts.count = count; + + return pubnub_get_members_ex(pb, channel_metadataid, opts); +} + + +enum pubnub_res pubnub_get_members_ex(pubnub_t* pb, + char const* channel, + struct pubnub_members_opts opts) { enum pubnub_res rslt; @@ -424,12 +717,14 @@ enum pubnub_res pubnub_get_members(pubnub_t* pb, } pb->trans = PBTT_GET_MEMBERS; rslt = pbcc_get_members_prep(&pb->core, - channel_metadataid, - include, - limit, - start, - end, - count, + channel, + opts.include, + opts.limit, + opts.page.next, + opts.page.prev, + opts.filter, + opts.sort, + opts.count, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_GET_MEMBERS; @@ -450,6 +745,7 @@ enum pubnub_res pubnub_add_members(pubnub_t* pb, { char obj_buffer[PUBNUB_BUF_MAXLEN]; enum pubnub_res rslt; + struct pubnub_members_opts defaults = pubnub_members_defopts(); PUBNUB_ASSERT(pb_valid_ctx_ptr(pb)); @@ -470,6 +766,12 @@ enum pubnub_res pubnub_add_members(pubnub_t* pb, channel_metadataid, include, update_obj, + defaults.filter, + defaults.sort, + defaults.limit, + defaults.page.next, + defaults.page.prev, + defaults.count, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_ADD_MEMBERS; @@ -488,6 +790,18 @@ enum pubnub_res pubnub_set_members(pubnub_t* pb, char const* channel_metadataid, char const* include, char const* set_obj) +{ + struct pubnub_members_opts opts = pubnub_members_defopts(); + opts.include = include; + + return pubnub_set_members_ex(pb, channel_metadataid, set_obj, opts); +} + + +enum pubnub_res pubnub_set_members_ex(pubnub_t* pb, + char const* channel, + char const* uuids, + struct pubnub_members_opts opts) { enum pubnub_res rslt; char obj_buffer[PUBNUB_BUF_MAXLEN]; @@ -505,13 +819,19 @@ enum pubnub_res pubnub_set_members(pubnub_t* pb, "pubnub_set_members", obj_buffer, "{\"set\":", - set_obj); + uuids); pb->method = pubnubUsePATCH; pb->trans = PBTT_SET_MEMBERS; rslt = pbcc_set_members_prep(&pb->core, - channel_metadataid, - include, - set_obj, + channel, + opts.include, + uuids, + opts.filter, + opts.sort, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_SET_MEMBERS; @@ -526,10 +846,23 @@ enum pubnub_res pubnub_set_members(pubnub_t* pb, } + enum pubnub_res pubnub_remove_members(pubnub_t* pb, char const* channel_metadataid, char const* include, char const* remove_obj) +{ + struct pubnub_members_opts opts = pubnub_members_defopts(); + opts.include = include; + + return pubnub_remove_members_ex(pb, channel_metadataid, remove_obj, opts); +} + + +enum pubnub_res pubnub_remove_members_ex(pubnub_t* pb, + char const* channel, + char const* uuids, + struct pubnub_members_opts opts) { enum pubnub_res rslt; char obj_buffer[PUBNUB_BUF_MAXLEN]; @@ -547,13 +880,19 @@ enum pubnub_res pubnub_remove_members(pubnub_t* pb, "pubnub_remove_members", obj_buffer, "{\"delete\":", - remove_obj); + uuids); pb->method = pubnubUsePATCH; pb->trans = PBTT_REMOVE_MEMBERS; rslt = pbcc_set_members_prep(&pb->core, - channel_metadataid, - include, - remove_obj, + channel, + opts.include, + uuids, + opts.filter, + opts.sort, + opts.limit, + opts.page.next, + opts.page.prev, + opts.count, pb->trans); if (PNR_STARTED == rslt) { pb->trans = PBTT_REMOVE_MEMBERS; @@ -567,5 +906,6 @@ enum pubnub_res pubnub_remove_members(pubnub_t* pb, return rslt; } + #endif /* PUBNUB_USE_OBJECTS_API */ diff --git a/core/pubnub_objects_api.h b/core/pubnub_objects_api.h index e487e174..73a61ded 100644 --- a/core/pubnub_objects_api.h +++ b/core/pubnub_objects_api.h @@ -9,7 +9,113 @@ #include "pubnub_api_types.h" #include "lib/pb_extern.h" -#include +/** Data pagination object. This object helps to paginate through the data. + It is more readable form of `start` and `end` parameters in objects API. + */ +struct pubnub_page_object { + /** The URL for the next page of results. If there is no next page, this field is null. */ + char const* next; + + /** The URL for the previous page of results. If there is no previous page, this field is null. */ + char const* prev; +}; + + +/** User data object. This object represents the user data. */ +struct pubnub_user_data { + + /** Name Display name for the user. */ + char const* name; + + /** User's identifier in an external system */ + char const* external_id; + + /** The URL of the user's profile picture */ + char const* profile_url; + + /** The user's email. */ + char const* email; + + /** JSON providing custom data about the user. Values must be scalar only; arrays or objects are not supported. + Filtering App Context data through the custom property is not recommended in SDKs. */ + char const* custom; +}; + + +/** Channel data object. This object represents the channel data. */ +struct pubnub_channel_data { + /** Display name for the channel. */ + char const* name; + + /** The channel's description. */ + char const* description; + + /** JSON providing custom data about the channel. Values must be scalar only; arrays or objects are not supported. + Filtering App Context data through the custom property is not recommended in SDKs. */ + char const* custom; +}; + + +/** The "null" page object, which is used to indicate that there is no next or previous page. + Also it can be used when there is no will to pass page as a parameter + */ +PUBNUB_EXTERN const struct pubnub_page_object pubnub_null_page; + + +/** The "null" user data object, which is used to indicate that there is no user data. + Also it can be used when there is no will to pass user data as a parameter + */ +PUBNUB_EXTERN const struct pubnub_user_data pubnub_null_user_data; + + +/** The "null" channel data object, which is used to indicate that there is no channel data. + Also it can be used when there is no will to pass channel data as a parameter + */ +PUBNUB_EXTERN const struct pubnub_channel_data pubnub_null_channel_data; + + +/** Options for the getall_*metadata functions */ +struct pubnub_getall_metadata_opts { + /** The comma delimited (C) string with additional/complex attributes to include in response. + Use NULL if you don't want to retrieve additional attributes. */ + char const* include; + + /** Expression used to filter the results. Only objects whose properties satisfy the given expression are returned. */ + char const* filter; + + /** Key-value pair of a property to sort by, and a sort direction. Available options are id, name, and updated. + Use asc or desc to specify sort direction, or specify null to take the default sort direction (ascending). + For example: {name: 'asc'} */ + char const* sort; + + /** Number of entities to return in response. Regular values 1 - 100. If you set `0`, + that means “use the default”. At the time of this writing, default was 100. */ + size_t limit; + + /** Pagination object. + @see pubnub_page_object */ + struct pubnub_page_object page; + + /** Request totalCount to be included in paginated response. By default, totalCount is omitted. */ + enum pubnub_tribool count; +}; + + +/** Default options for the set_*metadata functions + Values are set as follows: + - include: NULL + - filter: NULL + - sort: NULL + - limit: 100 + - page: pubnub_null_page + - count: pbccNotSet + + @see pubnub_getall_metadata_opts + @see pubnub_null_page + + @return Default options for the set_*metadata functions + */ +PUBNUB_EXTERN struct pubnub_getall_metadata_opts pubnub_getall_metadata_defopts(); /** Returns a paginated list of metadata objects for users associated with the subscription key of the context @p pbp, @@ -35,6 +141,21 @@ PUBNUB_EXTERN enum pubnub_res pubnub_getall_uuidmetadata(pubnub_t* pb, char const* end, enum pubnub_tribool count); + +/** Returns a paginated list of metadata objects for users associated with the subscription key of the context @p pbp, + optionally including each record's custom data object. + + Use `pubnub_getall_metadata_defopts()` to get the default options. + + @see pubnub_getall_metadata_defopts + + @param pb The pubnub context. Can't be NULL + @param opts The options for the getall_uuidmetadata function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_getall_uuidmetadata_ex(pubnub_t* pb, struct pubnub_getall_metadata_opts opts); + + /** Creates a metadata for a uuid with the attributes specified in @p uuid_metadata_obj. Returns the created metadata uuid object, optionally including the user's custom data object. @note User ID and name are required properties in the @p uuid_metadata_obj @@ -53,6 +174,47 @@ PUBNUB_EXTERN enum pubnub_res pubnub_set_uuidmetadata(pubnub_t* pb, char const* uuid_metadata_obj); +/** Options for the `pubnub_set_uuidmetadata_ex` function */ +struct pubnub_set_uuidmetadata_opts { + /** Uuid of the user. */ + char const* uuid; + + /** The comma delimited (C) string with additional/complex attributes to include in response. + Use NULL if you don't want to retrieve additional attributes. */ + char const* include; + + /** The user data object. */ + struct pubnub_user_data data; +}; + +/** Default options for the set_uuidmetadata functions + Values are set as follows: + - uuid: NULL (`pubnub_set_uuidmetadata_ex` will take the user_id from the context on NULL) + - include: NULL + - data: pubnub_null_user_data + + @see pubnub_null_user_data + + @return Default options for the set_uuidmetadata functions + */ +PUBNUB_EXTERN struct pubnub_set_uuidmetadata_opts pubnub_set_uuidmetadata_defopts(); + + +/** Creates a metadata for a uuid with the attributes specified in @p opts. + Returns the created metadata uuid object, optionally including the user's custom data object. + + Use `pubnub_set_uuidmetadata_defopts()` to get the default options. + + @see pubnub_set_uuidmetadata_defopts + + @param pb The pubnub context. Can't be NULL + @param uuid The UUID to create the metadata for. If NULL, the user_id will be taken from the context. + @param opts The options for the set_uuidmetadata function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_set_uuidmetadata_ex(pubnub_t* pb, struct pubnub_set_uuidmetadata_opts opts); + + /** Returns the uuid metadata object specified with @p user_id, optionally including the user's custom data object. @param pb The pubnub context. Can't be NULL @@ -67,7 +229,6 @@ PUBNUB_EXTERN enum pubnub_res pubnub_get_uuidmetadata(pubnub_t* pb, char const* uuid_metadataid); - /** Deletes the uuid metadata specified with @p uuid_metadataid. @param pb The pubnub context. Can't be NULL @param uuid_metadataid The UUID Metatdata ID. Cannot be NULL. @@ -100,6 +261,20 @@ PUBNUB_EXTERN enum pubnub_res pubnub_getall_channelmetadata(pubnub_t* pb, enum pubnub_tribool count); +/** Returns the spaces associated with the subscriber key of the context @p pbp, optionally + including each space's custom data object. + + Use `pubnub_getall_metadata_defopts()` to get the default options. + + @see pubnub_getall_metadata_defopts + + @param pb The pubnub context. Can't be NULL + @param opts The options for the getall_channelmetadata function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_getall_channelmetadata_ex(pubnub_t* pb, struct pubnub_getall_metadata_opts opts); + + /** Creates a metadata for the specified channel with the attributes specified in @p channel_metadata_obj. Returns the created space object, optionally including its custom data object. @note Channel ID and name are required properties of @p channel_metadata_obj @@ -115,6 +290,44 @@ PUBNUB_EXTERN enum pubnub_res pubnub_set_channelmetadata(pubnub_t* pb, char const* channel_metadata_obj); +/** Options for the `pubnub_set_channelmetadata_ex` function */ +struct pubnub_set_channelmetadata_opts { + /** The comma delimited (C) string with additional/complex attributes to include in response. + Use NULL if you don't want to retrieve additional attributes. */ + char const* include; + + /** The channel data object. */ + struct pubnub_channel_data data; +}; + + +/** Default options for the set_channelmetadata functions. + Values are set as follows: + - include: NULL + - data: pubnub_null_channel_data + + @see pubnub_null_channel_data + + @return Default options for the set_channelmetadata_ex function. + */ +PUBNUB_EXTERN struct pubnub_set_channelmetadata_opts pubnub_set_channelmetadata_defopts(); + + +/** Creates a metadata for the specified channel with the attributes specified in @p opts. + Returns the created space object, optionally including its custom data object. + + Use `pubnub_set_channelmetadata_defopts()` to get the default options. + + @see pubnub_set_channelmetadata_defopts + + @param pb The pubnub context. Can't be NULL + @param channel The channel to create the metadata for. If NULL, the channel will be taken from the context. + @param opts The options for the set_channelmetadata function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_set_channelmetadata_ex(pubnub_t* pb, char const* channel, struct pubnub_set_channelmetadata_opts opts); + + /** Returns the channel metadata object specified with @p channel_metadataid, optionally including its custom data object. @param pb The pubnub context. Can't be NULL @@ -137,6 +350,52 @@ PUBNUB_EXTERN enum pubnub_res pubnub_get_channelmetadata(pubnub_t* pb, PUBNUB_EXTERN enum pubnub_res pubnub_remove_channelmetadata(pubnub_t* pb, char const* channel_metadataid); +/** Options for the pubnub_get_memberships function */ +struct pubnub_membership_opts { + /** The UUID to retrieve the memberships. */ + char const* uuid; + + /** The comma delimited (C) string with additional/complex attributes to include in response. + Use NULL if you don't want to retrieve additional attributes. */ + char const* include; + + /** Expression used to filter the results. Only objects whose properties satisfy the given expression are returned. */ + char const* filter; + + /** Key-value pair of a property to sort by, and a sort direction. Available options are id, name, and updated. + Use asc or desc to specify sort direction, or specify null to take the default sort direction (ascending). + For example: {name: 'asc'} */ + char const* sort; + + /** Number of entities to return in response. Regular values 1 - 100. If you set `0`, + that means “use the default”. At the time of this writing, default was 100. */ + size_t limit; + + /** Pagination object. + @see pubnub_page_object */ + struct pubnub_page_object page; + + /** Request totalCount to be included in paginated response. By default, totalCount is omitted. */ + enum pubnub_tribool count; +}; + + +/** Default options for the pubnub_get_memberships function + Values are set as follows: + - uuid: NULL (`pubnub_*_memberships_ex` will take the user_id from the context on NULL) + - include: NULL + - filter: NULL + - sort: NULL + - limit: 100 + - page: pubnub_null_page + + @see pubnub_null_page + + @return Default options for the get_memberships function + */ +PUBNUB_EXTERN struct pubnub_membership_opts pubnub_memberships_defopts(); + + /** Returns the channel memberships of the user specified by @p uuid_metadataid, optionally including the custom data objects for... @param pb The pubnub context. Can't be NULL @@ -165,6 +424,20 @@ PUBNUB_EXTERN enum pubnub_res pubnub_get_memberships(pubnub_t* pb, enum pubnub_tribool count); +/** Returns the channel memberships of the user specified by @p uuid_metadataid, optionally including + the custom data objects for... + + Use `pubnub_memberships_defopts()` to get the default options. + + @see pubnub_memberships_defopts + + @param pb The pubnub context. Can't be NULL + @param opts The options for the get_memberships function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_get_memberships_ex(pubnub_t* pb, struct pubnub_membership_opts opts); + + /** Add/Update the channel memberships of the UUID specified by @p metadata_uuid. Uses the `set` property to perform those operations on one, or more memberships. An example for @set_obj: @@ -198,6 +471,37 @@ PUBNUB_EXTERN enum pubnub_res pubnub_set_memberships(pubnub_t* pb, char const* set_obj); +/** Add/Update the channel memberships of the UUID specified by @p metadata_uuid. Uses the `set` property + to perform those operations on one, or more memberships. + An example for @channels: + [ + { + "channel":{ "id": "main-channel-id" }, + "custom": { + "starred": true + } + }, + { + "channel":{ "id": "channel-0" }, + "some_key": { + "other_key": "other_value" + } + } + ] + + Use `pubnub_memberships_defopts()` to get the default options. + + @see pubnub_memberships_defopts + + @param pb The pubnub context. Can't be NULL + @param channels The JSON object that defines the add/update to perform. + Cannot be NULL. + @param opts The options for the set_memberships function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_set_memberships_ex(pubnub_t* pb, char const* channels, struct pubnub_membership_opts opts); + + /** Removes the memberships of the user specified by @p uuid_metadataid. Uses the `delete` property to perform those operations on one, or more memberships. An example for @remove_obj: @@ -225,6 +529,75 @@ PUBNUB_EXTERN enum pubnub_res pubnub_remove_memberships(pubnub_t* pb, char const* remove_obj); +/** Removes the memberships of the user specified by @p uuid_metadataid. Uses the `delete` property + to perform those operations on one, or more memberships. + An example for @channels: + [ + { + "channel":{ "id": "main-channel-id" } + }, + { + "channel":{ "id": "channel-0" } + } + ] + + Use `pubnub_memberships_defopts()` to get the default options. + + @see pubnub_memberships_defopts + + @param pb The pubnub context. Can't be null + @param channels The JSON object that defines the remove to perform. + Cannot be NULL. + @param opts The options for the remove_memberships function. + + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_remove_memberships_ex(pubnub_t* pb, char const* channels, struct pubnub_membership_opts opts); + + +/** Options for the pubnub_*_members functions */ +struct pubnub_members_opts { + /** The comma delimited (C) string with additional/complex attributes to include in response. + Use NULL if you don't want to retrieve additional attributes. */ + char const* include; + + /** Expression used to filter the results. Only objects whose properties satisfy the given expression are returned. */ + char const* filter; + + /** Key-value pair of a property to sort by, and a sort direction. Available options are id, name, and updated. + Use asc or desc to specify sort direction, or specify null to take the default sort direction (ascending). + For example: {name: 'asc'} */ + char const* sort; + + /** Number of entities to return in response. Regular values 1 - 100. If you set `0`, + that means “use the default”. At the time of this writing, default was 100. */ + size_t limit; + + /** Pagination object. + @see pubnub_page_object */ + struct pubnub_page_object page; + + /** Request totalCount to be included in paginated response. By default, totalCount is omitted. */ + enum pubnub_tribool count; +}; + + +/** Default options for the pubnub_get_members functions + Values are set as follows: + - include: NULL + - filter: NULL + - sort: NULL + - limit: 100 + - page: pubnub_null_page + - count: pbNotSet + + @see pubnub_null_page + + @return Default options for the get_members function + */ +PUBNUB_EXTERN struct pubnub_members_opts pubnub_members_defopts(); + + /** Returns all users in the channel specified with @p channel_metadataid, optionally including the custom data objects for... @param pb The pubnub context. Can't be NULL @@ -252,6 +625,21 @@ PUBNUB_EXTERN enum pubnub_res pubnub_get_members(pubnub_t* pb, enum pubnub_tribool count); +/** Returns all users in the channel specified with @p channel_metadataid, optionally including + the custom data objects for... + + Use `pubnub_get_members_defopts()` to get the default options. + + @see pubnub_get_members_defopts + + @param pb The pubnub context. Can't be NULL + @param channel The channel to retrieve the members for. + @param opts The options for the get_members function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_get_members_ex(pubnub_t* pb, char const* channel, struct pubnub_members_opts opts); + + /** Adds the list of members of the channel specified with @p channel_metadataid. Uses the `add` property to perform the operation on one or more members. An example for @add_obj: @@ -308,20 +696,47 @@ PUBNUB_EXTERN enum pubnub_res pubnub_set_members(pubnub_t* pb, char const* set_obj); +/** Updates the list of members of the space specified with @p space_id. Uses the `update` + property to perform the operation on one or more members. + An example for @uuids: + [ + { + "id": "some-user-id", + "custom": { + "starred": true + } + }, + { + "id": "user-0-id", + "some_key": { + "other_key": "other_value" + } + } + ] + + @param pb The pubnub context. Can't be NULL + @param channel The channel to add/update the members. + @param uuids The JSON object that defines the add/update to perform. Cannot be NULL. + @param opts The options for the set_members function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_set_members_ex(pubnub_t* pb, + char const* channel, + char const* uuids, + struct pubnub_members_opts opts); + + /** Removes the list of members of the space specified with @p space_id. Uses the `remove` property to perform the operation on one or more members. An example for @update_obj: [ - { - "id": "some-user-id", - "custom": { - "starred": true - } - }, - { - "id": "user-0-id" - } - ] + { + "uuid":{ "id": "main-user-id" } + }, + { + "uuid":{ "id": "user-0" } + } + ] @param pb The pubnub context. Can't be NULL @param channel_metadataid The Channel ID. @@ -336,6 +751,33 @@ PUBNUB_EXTERN enum pubnub_res pubnub_remove_members(pubnub_t* pb, char const* remove_obj); +/** Removes the list of members of the space specified with @p space_id. Uses the `remove` + property to perform the operation on one or more members. + An example for @uuids: + [ + { + "id": "some-user-id", + "custom": { + "starred": true + } + }, + { + "id": "user-0-id" + } + ] + + @param pb The pubnub context. Can't be NULL + @param channel The channel to remove the members. + @param uuids The JSON object that defines the remove to perform. Cannot be NULL. + @param opts The options for the remove_members function. + @return #PNR_STARTED on success, an error otherwise + */ +PUBNUB_EXTERN enum pubnub_res pubnub_remove_members_ex(pubnub_t* pb, + char const* channel, + char const* uuids, + struct pubnub_members_opts opts); + + #endif /* !defined INC_PUBNUB_OBJECTS_API */ #endif /* PUBNUB_USE_OBJECTS_API */ diff --git a/core/pubnub_version_internal.h b/core/pubnub_version_internal.h index c393fdd6..506e9917 100644 --- a/core/pubnub_version_internal.h +++ b/core/pubnub_version_internal.h @@ -3,7 +3,7 @@ #define INC_PUBNUB_VERSION_INTERNAL -#define PUBNUB_SDK_VERSION "4.11.2" +#define PUBNUB_SDK_VERSION "4.12.0" #endif /* !defined INC_PUBNUB_VERSION_INTERNAL */ diff --git a/core/samples/pubnub_objects_api_sample.c b/core/samples/pubnub_objects_api_sample.c new file mode 100644 index 00000000..7c84d1ad --- /dev/null +++ b/core/samples/pubnub_objects_api_sample.c @@ -0,0 +1,473 @@ +#include "pubnub_api_types.h" +#include "pubnub_blocking_io.h" +#include "pubnub_pubsubapi.h" +#include "core/pubnub_helper.h" +#include "core/pubnub_alloc.h" +#include "core/pubnub_ntf_sync.h" +#include "core/pubnub_objects_api.h" +#include +#include + +// This sample demo is split into 4 sections: +// 1. UUID metadata section +// 2. Channels metadata section +// 3. Memberships section +// 4. Members section +// +// You can navigate to each section by searching for the section name. +// +// Each section shows basic usage of the Pubnub Objects API. +// There are more options available for each API call, +// which can be found in the Pubnub Objects API documentation. + +static void sync_sample_free(pubnub_t* p); + +int main(void) { + // No demo keysets as app context is not applicable to it + char* publish_key = getenv("PUBNUB_PUBLISH_KEY"); + char* subscribe_key = getenv("PUBNUB_SUBSCRIBE_KEY"); + + enum pubnub_res result; + + pubnub_t* pb = pubnub_alloc(); + if (NULL == pb) { + printf("Failed to allocate Pubnub context!\n"); + return -1; + } + + pubnub_init(pb, publish_key, subscribe_key); + pubnub_set_user_id(pb, "my_user"); + + // Depending on requirements, you can use non-blocking I/O + pubnub_set_blocking_io(pb); + + printf("~~~~~~~~~~~~~~~~~~uuid metadata section~~~~~~~~~~~~~~~~~~\n"); + + printf("Set users' metadata\n"); + struct pubnub_set_uuidmetadata_opts set_opts = pubnub_set_uuidmetadata_defopts(); + set_opts.data.name = "my_name"; + set_opts.data.external_id = "my_external_id"; + set_opts.data.profile_url = "my_profile_url"; + set_opts.data.email = "my_email"; + set_opts.data.custom = "{\"key\":\"value\"}"; + set_opts.include = "custom"; + + // we didn't set the UUID, so it will be the one from the context + result = pubnub_set_uuidmetadata_ex(pb, set_opts); + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Set UUID metadata successful!\n"); + } else { + printf("Set UUID metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + struct pubnub_set_uuidmetadata_opts set_opts2 = pubnub_set_uuidmetadata_defopts(); + set_opts2.data.custom = "{\"key\":\"totally different value\"}"; + set_opts2.uuid = "some_user"; + + result = pubnub_set_uuidmetadata_ex(pb, set_opts2); + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Set UUID metadata successful!\n"); + } else { + printf("Set UUID metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + printf("Get users' metadata\n"); + struct pubnub_getall_metadata_opts getall_opts = pubnub_getall_metadata_defopts(); + // getall_opts.page.next = you can retrieve the next page in the response when the response is paginated + // getall_opts.page.prev = as above + getall_opts.limit = 1; + getall_opts.include = "custom"; + getall_opts.filter = "name=='my_name'"; + getall_opts.count = pbccTrue; + getall_opts.sort = "name:desc"; + + result = pubnub_getall_uuidmetadata_ex(pb, getall_opts); + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Get UUID metadata successful!\n"); + + for (const char* response = pubnub_get(pb); response != NULL; response = pubnub_get(pb)) { + printf("Response: %s\n", response); + } + } else { + printf("Get UUID metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Get users' metadata by UUID\n"); + result = pubnub_get_uuidmetadata(pb, "custom", "my_user"); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Get UUID metadata by UUID successful!\n"); + + const char* response = pubnub_get(pb); + printf("Response: %s\n", response); + } else { + printf("Get UUID metadata by UUID failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Remove users' metadata by UUID\n"); + + result = pubnub_remove_uuidmetadata(pb, "my_user"); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Remove UUID metadata successful!\n"); + } else { + printf("Remove UUID metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + result = pubnub_remove_uuidmetadata(pb, "some_user"); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Remove UUID metadata successful!\n"); + } else { + printf("Remove UUID metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + printf("~~~~~~~~~~~~~~~~channels metadata section~~~~~~~~~~~~~~~~\n"); + + printf("Set channels' metadata\n"); + struct pubnub_set_channelmetadata_opts set_channel_opts = pubnub_set_channelmetadata_defopts(); + set_channel_opts.data.name = "my_channel_name"; + set_channel_opts.data.description = "my_channel_description"; + set_channel_opts.data.custom = "{\"key\":\"value\"}"; + set_channel_opts.include = "custom"; + + result = pubnub_set_channelmetadata_ex(pb, "channel_id", set_channel_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Set channel metadata successful!\n"); + } else { + printf("Set channel metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Get channels' metadata\n"); + + struct pubnub_getall_metadata_opts getall_channel_opts = pubnub_getall_metadata_defopts(); + getall_channel_opts.limit = 1; + getall_channel_opts.include = "custom"; + getall_channel_opts.filter = "custom.key=='value'"; + getall_channel_opts.count = pbccTrue; + getall_channel_opts.sort = "name:desc"; + + result = pubnub_getall_channelmetadata_ex(pb, getall_channel_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Get channel metadata successful!\n"); + + for (const char* response = pubnub_get(pb); response != NULL; response = pubnub_get(pb)) { + printf("Response: %s\n", response); + } + } else { + printf("Get channel metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Get channels' metadata by channel ID\n"); + + result = pubnub_get_channelmetadata(pb, "custom", "channel_id"); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Get channel metadata by channel ID successful!\n"); + + const char* response = pubnub_get(pb); + printf("Response: %s\n", response); + } else { + printf("Get channel metadata by channel ID failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Remove channels' metadata by channel ID\n"); + result = pubnub_remove_channelmetadata(pb, "channel_id"); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Remove channel metadata successful!\n"); + } else { + printf("Remove channel metadata failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + printf("~~~~~~~~~~~~~~~~~~~memberships section~~~~~~~~~~~~~~~~~~~\n"); + + printf("Set users' memberships\n"); + struct pubnub_membership_opts set_memberships_opts = pubnub_memberships_defopts(); + set_memberships_opts.include = "custom"; + set_memberships_opts.limit = 1; + set_memberships_opts.sort = "channel.name:desc"; + set_memberships_opts.filter = "custom.key=='value'"; + set_memberships_opts.count = pbccTrue; + + const char* channels_meta = "[" + "{" + "\"channel\":{ \"id\": \"main-channel-id\" }," + "\"custom\": {" + "\"starred\": true" + "}" + "}," + "{" + "\"channel\":{ \"id\": \"channel-0\" }," + "\"some_key\": {" + "\"other_key\": \"other_value\"" + "}" + "}" + "]"; + + result = pubnub_set_memberships_ex(pb, channels_meta, set_memberships_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Set memberships successful!\n"); + } else { + printf("Set memberships failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Get users' memberships by UUID\n"); + + struct pubnub_membership_opts get_memberships_opts = pubnub_memberships_defopts(); + get_memberships_opts.limit = 1; + get_memberships_opts.include = "custom"; + get_memberships_opts.filter = "custom.starred==true"; + get_memberships_opts.count = pbccTrue; + get_memberships_opts.sort = "channel.id:desc"; + + result = pubnub_get_memberships_ex(pb, get_memberships_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Get memberships by UUID successful!\n"); + + const char* response = pubnub_get(pb); + printf("Response: %s\n", response); + } else { + printf("Get memberships by UUID failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Remove users' memberships by UUID\n"); + + struct pubnub_membership_opts remove_memberships_opts = pubnub_memberships_defopts(); + remove_memberships_opts.include = "custom"; + remove_memberships_opts.limit = 1; + remove_memberships_opts.sort = "channel.id:desc"; + remove_memberships_opts.filter = "custom.starred==true"; + remove_memberships_opts.count = pbccTrue; + + const char* channels_meta_remove = "[" + "{" + "\"channel\":{ \"id\": \"main-channel-id\" }" + "}," + "{" + "\"channel\":{ \"id\": \"channel-0\" }" + "}" + "]"; + + + result = pubnub_remove_memberships_ex(pb, channels_meta_remove, remove_memberships_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Remove memberships successful!\n"); + } else { + printf("Remove memberships failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + printf("~~~~~~~~~~~~~~~~~~~~~members section~~~~~~~~~~~~~~~~~~~~~\n"); + + printf("Set channels' members\n"); + + struct pubnub_members_opts set_members_opts = pubnub_members_defopts(); + set_members_opts.include = "custom"; + set_members_opts.limit = 1; + set_members_opts.sort = "uuid.id:desc"; + set_members_opts.filter = "custom.starred==true"; + set_members_opts.count = pbccTrue; + + const char* members_meta = "[" + "{" + "\"uuid\":{ \"id\": \"main-user-id\" }," + "\"custom\": {" + "\"starred\": true" + "}" + "}," + "{" + "\"uuid\":{ \"id\": \"user-0\" }," + "\"some_key\": {" + "\"other_key\": \"other_value\"" + "}" + "}" + "]"; + + result = pubnub_set_members_ex(pb, "channel_id", members_meta, set_members_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Set members successful!\n"); + } else { + printf("Set members failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Get channels' members\n"); + + struct pubnub_members_opts get_members_opts = pubnub_members_defopts(); + get_members_opts.limit = 1; + get_members_opts.include = "custom"; + get_members_opts.filter = "custom.starred==true"; + get_members_opts.count = pbccTrue; + get_members_opts.sort = "uuid.id:desc"; + + result = pubnub_get_members_ex(pb, "channel_id", get_members_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Get members successful!\n"); + + for (const char* response = pubnub_get(pb); response != NULL; response = pubnub_get(pb)) { + printf("Response: %s\n", response); + } + } else { + printf("Get members failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + sleep(1); + printf("Remove channels' members by UUID\n"); + + struct pubnub_members_opts remove_members_opts = pubnub_members_defopts(); + remove_members_opts.include = "custom"; + remove_members_opts.limit = 1; + remove_members_opts.sort = "uuid.id:desc"; + remove_members_opts.filter = "custom.starred==true"; + remove_members_opts.count = pbccTrue; + + const char* members_meta_remove = "[" + "{" + "\"uuid\":{ \"id\": \"main-user-id\" }" + "}," + "{" + "\"uuid\":{ \"id\": \"user-0\" }" + "}" + "]"; + + result = pubnub_remove_members_ex(pb, "channel_id", members_meta_remove, remove_members_opts); + + if (PNR_STARTED == result) { + result = pubnub_await(pb); + } + + if (PNR_OK == result) { + printf("Remove members successful!\n"); + } else { + printf("Remove members failed with code: %d('%s')\n", + result, + pubnub_res_2_string(result)); + } + + // ~~~~END OF SAMPLE~~~~ + + sync_sample_free(pb); + + return 0; +} + +static void sync_sample_free(pubnub_t* p) +{ + if (PN_CANCEL_STARTED == pubnub_cancel(p)) { + enum pubnub_res pnru = pubnub_await(p); + if (pnru != PNR_OK) { + printf("Awaiting cancel failed: %d('%s')\n", + pnru, + pubnub_res_2_string(pnru)); + } + } + if (pubnub_free(p) != 0) { + printf("Failed to free the Pubnub context\n"); + } +} + + diff --git a/posix/pubnub_version_posix.c b/posix/pubnub_version_posix.c index de1323c1..ffaa6ec6 100644 --- a/posix/pubnub_version_posix.c +++ b/posix/pubnub_version_posix.c @@ -6,6 +6,10 @@ #define PUBNUB_SDK_NAME "POSIX" +#ifndef PUBNUB_SDK_VERSION_SUFFIX +#define PUBNUB_SDK_VERSION_SUFFIX +#endif + char const *pubnub_sdk_name(void) { @@ -21,12 +25,12 @@ char const *pubnub_version(void) char const *pubnub_uname(void) { - return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION; + return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION PUBNUB_SDK_VERSION_SUFFIX; } char const *pubnub_uagent(void) { - return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION; + return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION PUBNUB_SDK_VERSION_SUFFIX; } diff --git a/windows/pubnub_version_windows.c b/windows/pubnub_version_windows.c index 8ba0b199..684c874b 100644 --- a/windows/pubnub_version_windows.c +++ b/windows/pubnub_version_windows.c @@ -6,6 +6,10 @@ #define PUBNUB_SDK_NAME "Windows" +#ifndef PUBNUB_SDK_VERSION_SUFFIX +#define PUBNUB_SDK_VERSION_SUFFIX +#endif + char const *pubnub_sdk_name(void) { @@ -21,11 +25,11 @@ char const *pubnub_version(void) char const *pubnub_uname(void) { - return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION; + return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION PUBNUB_SDK_VERSION_SUFFIX; } char const *pubnub_uagent(void) { - return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION; + return PUBNUB_SDK_NAME "-PubNub-C-core/" PUBNUB_SDK_VERSION PUBNUB_SDK_VERSION_SUFFIX; }