Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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)
Example #9
0
def test_comma_separated_string_with_iterable(iterable):
    assert comma_separated_string(iterable) == ",".join(iterable)
Example #10
0
def test_comma_separated_string(string):
    assert comma_separated_string(string) == string
Example #11
0
    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)
Example #12
0
    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)
Example #13
0
    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)