def create(self, name: str, channels: Union[str, Iterable] = None, description: str = None, handle: str = None, include_count: bool = None, **kwargs) -> Response: """ Create a User Group https://api.slack.com/methods/usergroups.create :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param name: A name for the User Group. Must be unique among User Groups. :type str: e.g. My Test Team :param channels: A comma separated string of encoded channel IDs for which the User Group uses as a default. :type Union[str, Iterable]: e.g. C1234567890,C2345678901,C3456789012 :param description: A short description of the User Group. :type str: :param handle: A mention handle. Must be unique among channels, users and User Groups. :type str: e.g. marketing :param include_count: Include the number of users in each User Group. :type bool: e.g. true :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.usergroups.create(**your_params) <Response [200]> """ payload = {"token": self._token, "name": name} if channels is not None: payload["channels"] = comma_separated_string(channels) if description is not None: payload["description"] = description if handle is not None: payload["handle"] = handle if include_count is not None: payload["include_count"] = include_count return self._post("usergroups.create", payload=payload, **kwargs)
def exchange(self, users: Union[str, Iterable], to_old: bool = None, **kwargs) -> Response: """ For Enterprise Grid workspaces, map local user IDs to global user IDs https://api.slack.com/methods/migration.exchange :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param users: A comma-separated list of user ids, up to 400 per request :type Union[str, Iterable]: :param to_old: Specify true to convert W global user IDs to workspace-specific U IDs. Defaults to false. :type bool: e.g. true :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.migration.exchange(**your_params) <Response [200]> >>> response.json() { "ok": true, "team_id": "T1KR7PE1W", "enterprise_id": "E1KQTNXE1", "user_id_map": { "U06UBSUN5": "W06M56XJM", "U06UEB62U": "W06PTT6GH", "U06UBSVB3": "W06PUUDLY", "U06UBSVDX": "W06PUUDMW", "W06UAZ65Q": "W06UAZ65Q" }, "invalid_user_ids": [ "U21ABZZXX" ] } """ if users is not None: users = comma_separated_string(users) payload = {"token": self._token, "users": users} if to_old is not None: payload["to_old"] = to_old return self._get("migration.exchange", payload=payload, **kwargs)
def open(self, channel: str = None, return_im: bool = None, users: Union[str, Iterable] = None, **kwargs) -> Response: """ Opens or resumes a direct message or multi-person direct message. https://api.slack.com/methods/conversations.open :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param channel: Resume a conversation by supplying an im or mpim's ID. Or provide the users field instead. :type str: e.g. G1234567890 :param return_im: Boolean, indicates you want the full IM channel definition in the response. :type bool: e.g. true :param users: Comma separated lists of users. If only one user is included, this creates a 1:1 DM. The ordering of the users is preserved whenever a multi-person direct message is returned. Supply a channel when not supplying users. :type Union[str, Iterable]: e.g. W1234567890,U2345678901,U3456789012 :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.conversations.open(**your_params) <Response [200]> >>> response.json() { "ok": true, "channel": { "id": "D069C7QFK" } } """ payload = {"token": self._token} if channel is not None: payload["channel"] = channel if return_im is not None: payload["return_im"] = return_im if users is not None: payload["users"] = comma_separated_string(users) return self._post("conversations.open", payload=payload, **kwargs)
def request(self, scopes: Union[str, Iterable], trigger_id: str, user: str, **kwargs) -> Response: """ Enables an app to trigger a permissions modal to grant an app access to a user access scope. https://api.slack.com/methods/apps.permissions.users.request :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param scopes: A comma separated list of user scopes to request for :type Union[str, Iterable]: :param trigger_id: Token used to trigger the request :type str: :param user: The user this scope is being requested for :type str: :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.apps.permissions.users.request(**your_params) <Response [200]> >>> response.json() { "ok": true } """ if scopes is not None: scopes = comma_separated_string(scopes) payload = { "token": self._token, "scopes": scopes, "trigger_id": trigger_id, "user": user, } return self._get("apps.permissions.users.request", payload=payload, **kwargs)
def share( self, channels: Union[str, Iterable], external_id: int = None, file: str = None, **kwargs ) -> Response: """ Share a remote file into a channel. https://api.slack.com/methods/files.remote.share :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param channels: Comma-separated list of channel IDs where the file will be shared. :type Union[str, Iterable]: e.g. C1234567890,C2345678901,C3456789012 :param external_id: The globally unique identifier (GUID) for the file, as set by the app registering the file with Slack. Either this field or file or both are required. :type int: e.g. 123456 :param file: Specify a file registered with Slack by providing its ID. Either this field or external_id or both are required. :type str: e.g. F2147483862 :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.files.remote.share(**your_params) <Response [200]> """ if channels is not None: channels = comma_separated_string(channels) payload = {"token": self._token, "channels": channels} if external_id is not None: payload["external_id"] = external_id if file is not None: payload["file"] = file return self._get("files.remote.share", payload=payload, **kwargs)
def team_info(self, users: Union[str, Iterable], **kwargs) -> Response: """ Retrieves the Do Not Disturb status for up to 50 users on a team. https://api.slack.com/methods/dnd.teamInfo :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param users: Comma-separated list of users to fetch Do Not Disturb status for :type Union[str, Iterable]: e.g. U1234,W4567 :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.dnd.team_info(**your_params) <Response [200]> >>> response.json() { "ok": true, "users": { "U023BECGF": { "dnd_enabled": true, "next_dnd_start_ts": 1450387800, "next_dnd_end_ts": 1450423800 }, "W058CJVAA": { "dnd_enabled": false, "next_dnd_start_ts": 1, "next_dnd_end_ts": 1 } } } """ if users is not None: users = comma_separated_string(users) payload = {"token": self._token, "users": users} return self._get("dnd.teamInfo", payload=payload, **kwargs)
def update(self, usergroup: str, users: Union[str, Iterable], include_count: bool = None, **kwargs) -> Response: """ Update the list of users for a User Group https://api.slack.com/methods/usergroups.users.update :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param usergroup: The encoded ID of the User Group to update. :type str: e.g. S0604QSJC :param users: A comma separated string of encoded user IDs that represent the entire list of users for the User Group. :type Union[str, Iterable]: e.g. U060R4BJ4,U060RNRCZ :param include_count: Include the number of users in the User Group. :type bool: e.g. true :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.usergroups.users.update(**your_params) <Response [200]> >>> response.json() { "ok": true, "usergroup": { "id": "S0616NG6M", "team_id": "T060R4BHN", "is_usergroup": true, "name": "Marketing Team", "description": "Marketing gurus, PR experts and product advocates.", "handle": "marketing-team", "is_external": false, "date_create": 1447096577, "date_update": 1447102109, "date_delete": 0, "auto_type": null, "created_by": "U060R4BJ4", "updated_by": "U060R4BJ4", "deleted_by": null, "prefs": { "channels": [], "groups": [] }, "users": [ "U060R4BJ4", "U060RNRCZ" ], "user_count": 1 } } """ if users is not None: users = comma_separated_string(users) payload = { "token": self._token, "usergroup": usergroup, "users": users, } if include_count is not None: payload["include_count"] = include_count return self._post("usergroups.users.update", payload=payload, **kwargs)
def update(self, usergroup: str, channels: Union[str, Iterable] = None, description: str = None, handle: str = None, include_count: bool = None, name: str = None, **kwargs) -> Response: """ Update an existing User Group https://api.slack.com/methods/usergroups.update :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param usergroup: The encoded ID of the User Group to update. :type str: e.g. S0604QSJC :param channels: A comma separated string of encoded channel IDs for which the User Group uses as a default. :type Union[str, Iterable]: e.g. C1234567890,C2345678901,C3456789012 :param description: A short description of the User Group. :type str: :param handle: A mention handle. Must be unique among channels, users and User Groups. :type str: e.g. marketing :param include_count: Include the number of users in the User Group. :type bool: e.g. true :param name: A name for the User Group. Must be unique among User Groups. :type str: e.g. My Test Team :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.usergroups.update(**your_params) <Response [200]> >>> response.json() { "ok": true, "usergroup": { "id": "S0616NG6M", "team_id": "T060R4BHN", "is_usergroup": true, "name": "Marketing Team", "description": "Marketing gurus, PR experts and product advocates.", "handle": "marketing-team", "is_external": false, "date_create": 1447096577, "date_update": 1447102109, "date_delete": 0, "auto_type": null, "created_by": "U060R4BJ4", "updated_by": "U060R4BJ4", "deleted_by": null, "prefs": { "channels": [], "groups": [] }, "users": [ "U060R4BJ4", "U060RNRCZ" ], "user_count": 1 } } """ payload = {"token": self._token, "usergroup": usergroup} if channels is not None: payload["channels"] = comma_separated_string(channels) if description is not None: payload["description"] = description if handle is not None: payload["handle"] = handle if include_count is not None: payload["include_count"] = include_count if name is not None: payload["name"] = name return self._post("usergroups.update", payload=payload, **kwargs)
def test_comma_separated_string_with_iterable(iterable): assert comma_separated_string(iterable) == ",".join(iterable)
def test_comma_separated_string(string): assert comma_separated_string(string) == string
def list(self, cursor: str = None, exclude_archived: bool = None, limit: int = None, types: Union[str, Iterable] = None, **kwargs) -> Response: """ Lists all channels in a Slack team. https://api.slack.com/methods/conversations.list :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param cursor: Paginate through collections of data by setting the cursor parameter to a next_cursor attribute returned by a previous request's response_metadata. Default value fetches the first "page" of the collection. See pagination for more detail. :type str: e.g. dXNlcjpVMDYxTkZUVDI= :param exclude_archived: Set to true to exclude archived channels from the list :type bool: e.g. true :param limit: The maximum number of items to return. Fewer than the requested number of items may be returned, even if the end of the list hasn't been reached. Must be an integer no larger than 1000. :type int: e.g. 20 :param types: Mix and match channel types by providing a comma-separated list of any combination of public_channel, private_channel, mpim, im :type Union[str, Iterable]: e.g. public_channel,private_channel :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.conversations.list(**your_params) <Response [200]> >>> response.json() { "ok": true, "channels": [ { "id": "C012AB3CD", "name": "general", "is_channel": true, "is_group": false, "is_im": false, "created": 1449252889, "creator": "U012A3CDE", "is_archived": false, "is_general": true, "unlinked": 0, "name_normalized": "general", "is_shared": false, "is_ext_shared": false, "is_org_shared": false, "pending_shared": [], "is_pending_ext_shared": false, "is_member": true, "is_private": false, "is_mpim": false, "topic": { "value": "Company-wide announcements and work-based matters", "creator": "", "last_set": 0 }, "purpose": { "value": "This channel is for team-wide communication and announcements. All team members are in this channel.", "creator": "", "last_set": 0 }, "previous_names": [], "num_members": 4 }, { "id": "C061EG9T2", "name": "random", "is_channel": true, "is_group": false, "is_im": false, "created": 1449252889, "creator": "U061F7AUR", "is_archived": false, "is_general": false, "unlinked": 0, "name_normalized": "random", "is_shared": false, "is_ext_shared": false, "is_org_shared": false, "pending_shared": [], "is_pending_ext_shared": false, "is_member": true, "is_private": false, "is_mpim": false, "topic": { "value": "Non-work banter and water cooler conversation", "creator": "", "last_set": 0 }, "purpose": { "value": "A place for non-work-related flimflam, faffing, hodge-podge or jibber-jabber you'd prefer to keep out of more focused work-related channels.", "creator": "", "last_set": 0 }, "previous_names": [], "num_members": 4 } ], "response_metadata": { "next_cursor": "dGVhbTpDMDYxRkE1UEI=" } } """ payload = {"token": self._token} if cursor is not None: payload["cursor"] = cursor if exclude_archived is not None: payload["exclude_archived"] = exclude_archived if limit is not None: payload["limit"] = limit if types is not None: payload["types"] = comma_separated_string(types) return self._get("conversations.list", payload=payload, **kwargs)
def invite(self, channel: str, users: Union[str, Iterable], **kwargs) -> Response: """ Invites users to a channel. https://api.slack.com/methods/conversations.invite :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param channel: The ID of the public or private channel to invite user(s) to. :type str: e.g. C1234567890 :param users: A comma separated list of user IDs. Up to 1000 users may be listed. :type Union[str, Iterable]: e.g. W1234567890,U2345678901,U3456789012 :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.conversations.invite(**your_params) <Response [200]> >>> response.json() { "ok": true, "channel": { "id": "C012AB3CD", "name": "general", "is_channel": true, "is_group": false, "is_im": false, "created": 1449252889, "creator": "W012A3BCD", "is_archived": false, "is_general": true, "unlinked": 0, "name_normalized": "general", "is_read_only": false, "is_shared": false, "is_ext_shared": false, "is_org_shared": false, "pending_shared": [], "is_pending_ext_shared": false, "is_member": true, "is_private": false, "is_mpim": false, "last_read": "1502126650.228446", "topic": { "value": "For public discussion of generalities", "creator": "W012A3BCD", "last_set": 1449709364 }, "purpose": { "value": "This part of the workspace is for fun. Make fun here.", "creator": "W012A3BCD", "last_set": 1449709364 }, "previous_names": [ "specifics", "abstractions", "etc" ], "num_members": 23, "locale": "en-US" } } """ if users is not None: users = comma_separated_string(users) payload = {"token": self._token, "channel": channel, "users": users} return self._post("conversations.invite", payload=payload, **kwargs)
def upload( self, channels: Union[str, Iterable] = None, content: Union[str, PathLike, IO] = None, file: Union[str, PathLike, IO] = None, filename: str = None, filetype: str = None, initial_comment: str = None, thread_ts: float = None, title: str = None, **kwargs ) -> Response: """ Uploads or creates a file. https://api.slack.com/methods/files.upload :param token: Authentication token bearing required scopes. :type str: e.g. xxxx-xxxxxxxxx-xxxx :param channels: Comma-separated list of channel names or IDs where the file will be shared. :type Union[str, Iterable]: e.g. C1234567890,C2345678901,C3456789012 :param content: File contents via a POST variable. If omitting this parameter, you must provide a file. :type Union[str, PathLike, IO]: e.g. '/absolute/path/to/file' or actual IO file :param file: File contents via multipart/form-data. If omitting this parameter, you must submit content. :type Union[str, PathLike, IO]: e.g. '/absolute/path/to/file' or actual IO file :param filename: Filename of file. :type str: e.g. foo.txt :param filetype: A file type identifier. :type str: e.g. php :param initial_comment: The message text introducing the file in specified channels. :type str: e.g. Best! :param thread_ts: Provide another message's ts value to upload this file as a reply. Never use a reply's ts value; use its parent instead. :type float: e.g. 1234567890.123456 :param title: Title of file. :type str: e.g. My File :returns response: :type requests.Response: e.g. <Response [200]> example: >>> client = SlackTime(token='insert-your-token-here') >>> response = client.files.upload(**your_params) <Response [200]> >>> response.json() { "ok": true, "file": { "id": "F0TD00400", "created": 1532293501, "timestamp": 1532293501, "name": "dramacat.gif", "title": "dramacat", "mimetype": "image/jpeg", "filetype": "gif", "pretty_type": "JPEG", "user": "******", "editable": false, "size": 43518, "mode": "hosted", "is_external": false, "external_type": "", "is_public": false, "public_url_shared": false, "display_as_bot": false, "username": "", "url_private": "https://.../dramacat.gif", "url_private_download": "https://.../dramacat.gif", "thumb_64": "https://.../dramacat_64.gif", "thumb_80": "https://.../dramacat_80.gif", "thumb_360": "https://.../dramacat_360.gif", "thumb_360_w": 360, "thumb_360_h": 250, "thumb_480": "https://.../dramacat_480.gif", "thumb_480_w": 480, "thumb_480_h": 334, "thumb_160": "https://.../dramacat_160.gif", "image_exif_rotation": 1, "original_w": 526, "original_h": 366, "permalink": "https://.../dramacat.gif", "permalink_public": "https://.../More-Path-Components", "comments_count": 0, "is_starred": false, "shares": { "private": { "D0L4B9P0Q": [ { "reply_users": [], "reply_users_count": 0, "reply_count": 0, "ts": "1532293503.000001" } ] } }, "channels": [], "groups": [], "ims": [ "D0L4B9P0Q" ], "has_rich_preview": false } } """ payload = {"token": self._token} if channels is not None: payload["channels"] = comma_separated_string(channels) if content is not None: file_to_upload = make_file(content) payload["content"] = file_to_upload if file is not None: file_to_upload = make_file(file) kwargs["files"] = {"file": file_to_upload} if filename is not None: payload["filename"] = filename if filetype is not None: payload["filetype"] = filetype if initial_comment is not None: payload["initial_comment"] = initial_comment if thread_ts is not None: payload["thread_ts"] = thread_ts if title is not None: payload["title"] = title return self._post("files.upload", payload=payload, **kwargs)