Skip to content
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion api_client_generation/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ code_gen_dir=`pwd`
project_root=$code_gen_dir/..
echo $code_gen_dir

commit_hash=ab10aa5263cfed89ddae0720cea31eca0c06a003
commit_hash=b63d67cc0ed7c5a3962e72f21001df4d2ed482f2
api_spec_base_url=https://raw.githubusercontent.com/symphonyoss/symphony-api-spec/${commit_hash}
echo $api_spec_base_url

Expand Down
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions symphony/bdk/core/config/model/bdk_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def __init__(self, **config):
self.datafeed = BdkDatafeedConfig(config.get("datafeed"))
self.datahose = BdkDatahoseConfig(config.get("datahose"))
self.retry = BdkRetryConfig(config.get("retry"))
self.manifest = config.get("manifest")

def is_bot_configured(self) -> bool:
"""
Expand Down
43 changes: 40 additions & 3 deletions symphony/bdk/core/service/stream/stream_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,31 +136,35 @@ async def list_streams_one_page(skip, limit):

@retry
async def search_rooms(self, query: V2RoomSearchCriteria, skip: int = 0,
limit: int = 50) -> V3RoomSearchResults:
limit: int = 50, include_non_discoverable=False) -> V3RoomSearchResults:
"""Search for rooms according to the specified criteria.
Wraps the `Search Rooms V3 <https://developers.symphony.com/restapi/reference/search-rooms-v3>`_ endpoint.

:param query: the search criteria.
:param skip: number of rooms to skip, defaults to 0.
:param limit: number of maximum rooms to return. Must be a positive integer that does not exceed 100.
:param include_non_discoverable: set to `True` to include rooms not publicly searchable, false by default.
:return: the rooms matching search criteria.
"""
return await self._streams_api.v3_room_search_post(query=query, skip=skip, limit=limit,
include_non_discoverable=include_non_discoverable,
session_token=await self._auth_session.session_token)

async def search_all_rooms(self, query: V2RoomSearchCriteria, chunk_size: int = 50,
max_number: int = None) -> AsyncGenerator[V3RoomDetail, None]:
max_number: int = None, include_non_discoverable : bool = False)\
-> AsyncGenerator[V3RoomDetail, None]:
"""Search for rooms according to the specified criteria.
Wraps the `Search Rooms V3 <https://developers.symphony.com/restapi/reference/search-rooms-v3>`_ endpoint.

:param query: the search criteria.
:param chunk_size: the maximum number of elements to retrieve in one underlying HTTP call.
:param max_number: the total maximum number of elements to retrieve.
:param include_non_discoverable: set to `True` to include rooms not publicly searchable, false by default.
:return: an asynchronous generator of the rooms matching the search criteria.
"""

async def search_rooms_one_page(skip, limit):
result = await self.search_rooms(query, skip, limit)
result = await self.search_rooms(query, skip, limit, include_non_discoverable)
return result.rooms if result.rooms else None

return offset_based_pagination(search_rooms_one_page, chunk_size, max_number)
Expand Down Expand Up @@ -346,6 +350,39 @@ async def list_streams_admin_one_page(skip, limit):

return offset_based_pagination(list_streams_admin_one_page, chunk_size, max_number)

@retry
async def list_user_streams_admin(self, uid: int, stream_filter: StreamFilter = None, skip: int = 0,
limit: int = 50) -> StreamList:
"""Retrieve a list of all streams of which a user is a member.
Wraps the `User Streams <https://developers.symphony.com/restapi/v20.16/reference#user-streams>`_ endpoint.

:param uid: the ID of the user.
:param stream_filter: the filtering criteria for the streams.
:param skip: the number of streams to skip.
:param limit: the maximum number of streams to retrieve. Must be less or equal than 1000.
:return: the list of streams for the specified user.
"""
return await self._streams_api.v1_admin_user_uid_streams_list_post(
uid=uid, filter=stream_filter, skip=skip, limit=limit, session_token=await self._auth_session.session_token
)

async def list_all_user_streams_admin(self, uid: int, stream_filter: StreamFilter = None, chunk_size: int = 50,
max_number: int = None) -> AsyncGenerator[StreamAttributes, None]:
"""Retrieves all streams of which a user is a member, handling pagination automatically.
Wraps the `User Streams <https://developers.symphony.com/restapi/v20.16/reference#user-streams>`_ endpoint.

:param uid: the ID of the user.
:param stream_filter: the filtering criteria for the streams.
:param chunk_size: the maximum number of streams to retrieve in one underlying HTTP call.
:param max_number: the total maximum number of streams to retrieve.
:return: an asynchronous generator of the streams.
"""
async def list_streams_one_page(skip, limit):
result = await self.list_user_streams_admin(uid, stream_filter, skip, limit)
return result.value if result else None

return offset_based_pagination(list_streams_one_page, chunk_size, max_number)

@retry
async def list_stream_members(self, stream_id: str, skip: int = 0, limit: int = 100) -> V2MembershipList:
"""List the current members of an existing stream. The stream can be of type IM, MIM, or ROOM.
Expand Down
44 changes: 43 additions & 1 deletion symphony/bdk/core/service/user/user_service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import base64
import json
from pathlib import Path
from typing import Union, AsyncGenerator

from symphony.bdk.core.auth.auth_session import AuthSession
Expand All @@ -21,6 +23,7 @@
from symphony.bdk.gen.pod_model.followers_list_response import FollowersListResponse
from symphony.bdk.gen.pod_model.following_list_response import FollowingListResponse
from symphony.bdk.gen.pod_model.role_detail import RoleDetail
from symphony.bdk.gen.pod_model.service_account_manifest import ServiceAccountManifest
from symphony.bdk.gen.pod_model.string_id import StringId
from symphony.bdk.gen.pod_model.user_filter import UserFilter
from symphony.bdk.gen.pod_model.user_id_list import UserIdList
Expand Down Expand Up @@ -260,10 +263,12 @@ def __init__(self, user_api: UserApi,
audit_trail_api: AuditTrailApi,
system_api: SystemApi,
auth_session: AuthSession,
retry_config: BdkRetryConfig):
retry_config: BdkRetryConfig,
manifest: str):
super().__init__(user_api, users_api, auth_session, retry_config)
self._audit_trail_api = audit_trail_api
self._system_api = system_api
self._manifest = manifest

@retry
async def get_user_detail(
Expand Down Expand Up @@ -898,3 +903,40 @@ async def unsuspend(
}

await self._user_api.v1_admin_user_user_id_suspension_update_put(**params)

@retry
async def update_manifest_from_json(self, manifest_data: str) -> None:
"""
Updates the user manifest from a JSON string.

:param manifest_data: A JSON string.
:raises json.JSONDecodeError: If the string is not valid JSON.
"""
await self._user_api.v1_user_manifest_own_post(
session_token=await self._auth_session.session_token,
manifest=ServiceAccountManifest(manifest_data)
)

async def update_manifest_from_file(self) -> None:
"""
Updates the user manifest using the file mentioned in config.yaml under 'manifest'.

:raises FileNotFoundError: If the file does not exist.
:raises json.JSONDecodeError: If the file content is not valid JSON.
:raises IOError: If the file can't be read.
"""
file_path = Path(self._manifest)

with file_path.open('r', encoding='utf-8') as f:
content = json.load(f)
manifest_text = json.dumps(content)

await self._user_api.v1_user_manifest_own_post(
session_token=await self._auth_session.session_token,
manifest=ServiceAccountManifest(manifest_text)
)

@retry
async def get_manifest(self) -> ServiceAccountManifest:
"""Retrieves own user manifest"""
return await self._user_api.v1_user_manifest_own_get(session_token=await self._auth_session.session_token)
3 changes: 2 additions & 1 deletion symphony/bdk/core/service_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ def get_user_service(self) -> UserService:
AuditTrailApi(self._agent_client),
PodSystemApi(self._pod_client),
self._auth_session,
self._config.retry
self._config.retry,
self._config.manifest
)

def get_message_service(self) -> MessageService:
Expand Down
28 changes: 10 additions & 18 deletions symphony/bdk/gen/agent_api/attachments_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

This document refers to Symphony API calls to send and receive messages and content. They need the on-premise Agent installed to perform decryption/encryption of content. - sessionToken and keyManagerToken can be obtained by calling the authenticationAPI on the symphony back end and the key manager respectively. Refer to the methods described in authenticatorAPI.yaml. - Actions are defined to be atomic, ie will succeed in their entirety or fail and have changed nothing. - If it returns a 40X status then it will have sent no message to any stream even if a request to some subset of the requested streams would have succeeded. - If this contract cannot be met for any reason then this is an error and the response code will be 50X. - MessageML is a markup language for messages. See reference here: https://rest-api.symphony.com/docs/messagemlv2 - **Real Time Events**: The following events are returned when reading from a real time messages and events stream (\"datafeed\"). These events will be returned for datafeeds created with the v5 endpoints. To know more about the endpoints, refer to Create Messages/Events Stream and Read Messages/Events Stream. Unless otherwise specified, all events were added in 1.46. # noqa: E501

The version of the OpenAPI document: 22.9.1
The version of the OpenAPI document: 24.12.1
Generated by: https://openapi-generator.tech
"""

Expand Down Expand Up @@ -49,13 +49,12 @@ def __init__(self, api_client=None):
'all': [
'sid',
'session_token',
'key_manager_token',
'file',
'key_manager_token',
],
'required': [
'sid',
'session_token',
'key_manager_token',
'file',
],
'nullable': [
Expand All @@ -75,22 +74,22 @@ def __init__(self, api_client=None):
(str,),
'session_token':
(str,),
'key_manager_token':
(str,),
'file':
(file_type,),
'key_manager_token':
(str,),
},
'attribute_map': {
'sid': 'sid',
'session_token': 'sessionToken',
'key_manager_token': 'keyManagerToken',
'file': 'file',
'key_manager_token': 'keyManagerToken',
},
'location_map': {
'sid': 'path',
'session_token': 'header',
'key_manager_token': 'header',
'file': 'form',
'key_manager_token': 'header',
},
'collection_format_map': {
}
Expand Down Expand Up @@ -127,7 +126,6 @@ def __init__(self, api_client=None):
'file_id',
'message_id',
'session_token',
'key_manager_token',
],
'nullable': [
],
Expand Down Expand Up @@ -251,7 +249,6 @@ def v1_stream_sid_attachment_create_post(
self,
sid,
session_token,
key_manager_token,
file,
**kwargs
):
Expand All @@ -261,16 +258,16 @@ def v1_stream_sid_attachment_create_post(
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True

>>> thread = agent_api.v1_stream_sid_attachment_create_post(sid, session_token, key_manager_token, file, async_req=True)
>>> thread = agent_api.v1_stream_sid_attachment_create_post(sid, session_token, file, async_req=True)
>>> result = thread.get()

Args:
sid (str): Stream ID
session_token (str): Session authentication token.
key_manager_token (str): Key Manager authentication token.
file (file_type): The attachment body.

Keyword Args:
key_manager_token (str): Key Manager authentication token.. [optional]
_return_http_data_only (bool): response data without head status
code and headers. Default is True.
_preload_content (bool): if False, the urllib3.HTTPResponse object
Expand Down Expand Up @@ -331,8 +328,6 @@ def v1_stream_sid_attachment_create_post(
sid
kwargs['session_token'] = \
session_token
kwargs['key_manager_token'] = \
key_manager_token
kwargs['file'] = \
file
return self.v1_stream_sid_attachment_create_post_endpoint.call_with_http_info(**kwargs)
Expand All @@ -343,7 +338,6 @@ def v1_stream_sid_attachment_get(
file_id,
message_id,
session_token,
key_manager_token,
**kwargs
):
"""Download an attachment. # noqa: E501
Expand All @@ -352,17 +346,17 @@ def v1_stream_sid_attachment_get(
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True

>>> thread = agent_api.v1_stream_sid_attachment_get(sid, file_id, message_id, session_token, key_manager_token, async_req=True)
>>> thread = agent_api.v1_stream_sid_attachment_get(sid, file_id, message_id, session_token, async_req=True)
>>> result = thread.get()

Args:
sid (str): Stream ID
file_id (str): The attachment ID (Base64-encoded)
message_id (str): The ID of the message containing the attachment
session_token (str): Session authentication token.
key_manager_token (str): Key Manager authentication token.

Keyword Args:
key_manager_token (str): Key Manager authentication token.. [optional]
_return_http_data_only (bool): response data without head status
code and headers. Default is True.
_preload_content (bool): if False, the urllib3.HTTPResponse object
Expand Down Expand Up @@ -427,8 +421,6 @@ def v1_stream_sid_attachment_get(
message_id
kwargs['session_token'] = \
session_token
kwargs['key_manager_token'] = \
key_manager_token
return self.v1_stream_sid_attachment_get_endpoint.call_with_http_info(**kwargs)

def v3_stream_sid_attachment_create_post(
Expand Down
Loading
Loading