Source code for slacksound.slackapi

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: slackapi.py
#
# Copyright 2017 Oriol Fabregas
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to
#  deal in the Software without restriction, including without limitation the
#  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
#  sell copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
#

"""
Main code for slackapi

.. _Google Python Style Guide:
   http://google.github.io/styleguide/pyguide.html

"""

import logging
import tzlocal

from slackclient import SlackClient
from datetime import datetime

__author__ = '''Oriol Fabregas <fabregas.oriol@gmail.com>'''
__docformat__ = '''google'''
__date__ = '''2017-10-13'''
__copyright__ = '''Copyright 2017, Oriol Fabregas'''
__credits__ = ["Oriol Fabregas"]
__license__ = '''MIT'''
__maintainer__ = '''Oriol Fabregas'''
__email__ = '''<fabregas.oriol@gmail.com>'''
__status__ = '''Development'''  # "Prototype", "Development", "Production".


# This is the main prefix used for logging
LOGGER_BASENAME = '''slackapi'''
LOGGER = logging.getLogger(LOGGER_BASENAME)
LOGGER.addHandler(logging.NullHandler())


[docs]class Slack(object): """SlackClient Wrapper""" def __init__(self, token, bot=False): """ Initialise object. If bot is true it will use the RTM API Args: token: string bot: boolean """ self.client = SlackClient(token) if bot: self.client = SlackClient(token) self.client.rtm_connect() self.__channels = [] self.__users = [] self.__groups = [] @property def channels(self, **kwargs): """ Gets all channels in a Slack team. Args: **kwargs: extra kwargs Returns: list of Channel objects """ if not self.__channels: channels_list = self.client.api_call("channels.list", **kwargs) for channel in channels_list.get('channels', {}): self.__channels.append(Channel(self, channel)) return self.__channels @property def groups(self, **kwargs): """ Gets all groups in a Slack team. Args: **kwargs: extra kwargs Returns: list of Group objects """ if not self.__groups: groups_list = self.client.api_call("groups.list", **kwargs) for group in groups_list.get('groups', {}): self.__groups.append(Group(self, group)) return self.__groups @property def users(self, **kwargs): """ Gets all users in a Slack team. Args: **kwargs: extra kwargs Returns: list of Member objects """ if not self.__users: users_list = self.client.api_call("users.list", **kwargs) for user in users_list.get('members', []): self.__users.append(Member(user)) return self.__users
[docs] def get_channel_by_name(self, channel_name): """ Gets one channel in a Team Args: channel_name: string Returns: Channel object """ channel_object = None for channel in self.channels: if channel.name_normalized == channel_name: channel_object = channel return channel_object
[docs] def get_group_by_name(self, group_name): """ Gets one group in a Team Args: group_name: string Returns: Group object """ group_object = None for group in self.groups: if group.name_normalized == group_name: group_object = group return group_object
[docs] def post_message(self, message, channel): """ Posts a message in a group or channel as the user who is owner of the token Args: message: string channel: string Returns: """ self.client.api_call("chat.postMessage", channel=channel, text=message, as_user=True) return True
[docs]class Member(object): """ Model for a Member Not all attributes are populated here though. https://api.slack.com/types/user """ def __init__(self, member_details): """ Initialise object Args: member_details: dictionary """ self._member_details = member_details @property def color(self): """ Used in some clients to display a colored username. Returns: string """ return self._member_details.get('color', None) @property def deleted(self): """ Active/Inactive users Returns: boolean """ return self._member_details.get('deleted', None) @property def member_id(self): """ Member ID Returns: string """ return self._member_details.get('id', None) @property def is_admin(self): """ Whether this user is admin or not Returns: boolean """ return self._member_details.get('is_admin', None) @property def email(self): """ Email of the member Returns: string """ return self._member_details.get('profile').get('email', None)
[docs]class Group(object): """ Model for a group Not all attributes are populated here though. https://api.slack.com/types/group """ def __init__(self, slack_instance, group_details): """ Initialise object Args: slack_instance: SlackClient instance group_details: dictionary """ self._slack_instance = slack_instance self._group_details = group_details @property def group_id(self): """ Group ID Returns: string """ return self._group_details.get('id', None) @property def name(self): """ Name of the group Returns: string """ return self._group_details.get('name', None) @property def is_general(self): """ Whether the group is general or not Returns: boolean """ return self._group_details.get('is_general', None) @property def name_normalized(self): """ Normalized name of the group Returns: string """ return self._group_details.get('name_normalized', None) @property def created(self): """ Unix time converted to datetime object Returns: datetime object """ unix_timestamp = self._group_details.get('created', None) date = datetime.fromtimestamp(float(unix_timestamp), tzlocal.get_localzone()) return date @property def history(self): """ Chat history of the group Returns: list of Message objects """ ch_history = self._slack_instance.client.api_call( method="groups.history", channel=self.group_id) return [Message(history_message) for history_message in ch_history.get('messages')]
[docs]class Channel(object): """ Model for a Channel Not all attributes are populated here though. https://api.slack.com/types/channel """ def __init__(self, slack_instance, channel_details): """ Initialise object Args: slack_instance: SlackClient instance channel_details: dictionary """ self.__slack_instance = slack_instance self._channel_details = channel_details @property def channel_id(self): """ Channel ID Returns: string """ return self._channel_details.get('id', None) @property def name(self): """ Name of the channel Returns: string """ return self._channel_details.get('name', None) @property def is_general(self): """ Whether the channel is general or not Returns: boolean """ return self._channel_details.get('is_general', None) @property def name_normalized(self): """ Normalized name of the channel Returns: string """ return self._channel_details.get('name_normalized', None) @property def created(self): """ Unix time converted to datetime object Returns: datetime object """ unix_timestamp = self._channel_details.get('created', None) date = datetime.fromtimestamp(float(unix_timestamp), tzlocal.get_localzone()) return date @property def history(self): """ Chat history of the channel Returns: list of Message objects """ ch_history = self.__slack_instance.client.api_call( method="channels.history", channel=self.channel_id) return [Message(history_message) for history_message in ch_history.get('messages')]
[docs]class Message(object): """ Model for a Message Not all attributes are populated here though. https://api.slack.com/events/message """ def __init__(self, message_details): """ Initialise object Args: message_details: dictionary """ self._message_details = message_details @property def text(self): """ Text of the message Returns: string """ return self._message_details.get('text', None) @property def type(self): """ SubType of the Message Returns: string """ return self._message_details.get('type', None) @property def attachments(self): """ Attachments for a Message, if any Returns: list of Attachment objects """ return [Attachment(m_attachment) for m_attachment in self._message_details.get('attachments', [])] @property def user(self): """ ID of the user speaking or sent the message Returns: string """ return self._message_details.get('user', None) @property def datetime(self): """ Unix time converted to datetime object Returns: datetime object """ unix_timestamp = self._message_details.get('ts', None) date = datetime.fromtimestamp(float(unix_timestamp), tzlocal.get_localzone()) return date @property def unix_time(self): """ Unix time. Useful for time comparison Returns: float """ return float(self._message_details.get('ts', None)) @property def reaction(self): """ Reactions of the message Returns: list of Reaction objects """ return [Reaction(reaction) for reaction in self._message_details.get('reactions', [])]
[docs]class Reaction(object): """ Model for a Reaction These are Emoji icons for a message """ def __init__(self, reaction_details): """ Initialise object Args: reaction_details: dictionary """ self._reaction_details = reaction_details @property def count(self): """ Count of a reaction Returns: integer """ return self._reaction_details.get('count', None) @property def name(self): """ Name of the reaction Returns: string """ return self._reaction_details.get('name', None) @property def users(self): """ User IDs who reacted on the reaction Returns: list of user ID """ return self._reaction_details.get('users', [])
[docs]class Attachment(object): """ Model for an Attachment Not all attributes are populated here though. https://api.slack.com/docs/message-attachments """ def __init__(self, attachment_details): """ Initialise object Args: attachment_details: dictionary """ self._attachment_details = attachment_details @property def author_link(self): """ A valid URL that will hyperlink the author_name text mentioned above. Returns: string """ return self._attachment_details.get('author_link', None) @property def author_name(self): """ Small text used to display the author's name. Returns: string """ return self._attachment_details.get('author_name', None) @property def title(self): """ Title of the attachment Returns: string """ return self._attachment_details.get('title', None)