Ejemplo n.º 1
0
class SlackHandler(StreamHandler):
    """Slack log handler Class

    Inherits:
        logging.StreamHandler: Base log StreamHandler class.
    """
    def __init__(self,
                 channel: str,
                 slack_bot_token: str = None,
                 username: str = "Gytrash"):
        """Initialize the stream handler with some specifics for slack.

        Args:
            channel (str): Slack channel to publish logs
            slack_bot_token (str, optional): Slack bot token to use the slack published app. Defaults to None.
            username (str, optional): Username of the Slack bot. Defaults to "Gytrash".
        """
        StreamHandler.__init__(self)
        # Initialize a Web API client
        if slack_bot_token:
            self.slack_web_client = WebClient(token=slack_bot_token)
        else:
            self.slack_web_client = WebClient(
                token=os.environ["SLACK_BOT_TOKEN"])
        self.channel = channel
        self.username = username

    def _send_log(self, message: dict):
        """Posts the formatted message to slack via the web client.

        Args:
            message (dict): Slack message dictionary. Follows the blocks API.
        """
        self.slack_web_client.chat_postMessage(**message)

    def emit(self, message: "logging.LogRecord"):
        """Emits a message from the handler.

        Args:
            message (logging.LogRecord): Log record from the stream.
        """
        assert isinstance(message, logging.LogRecord)

        slack_message = self.format(message)

        # List of LogRecord attributes expected when reading the
        # documentation of the logging module:
        expected_attributes = (
            "args,asctime,created,exc_info,filename,funcName,levelname,"
            "levelno,lineno,module,msecs,message,msg,name,pathname,"
            "process,processName,relativeCreated,stack_info,thread,threadName")
        for ea in expected_attributes.split(","):
            if not hasattr(message, ea):
                print("UNEXPECTED: LogRecord does not have the '{}' field!".
                      format(ea))

        slack_message["channel"] = self.channel
        slack_message["username"] = self.username

        self._send_log(slack_message)
Ejemplo n.º 2
0
    def _send_to_listeners(self, message):
        channels = SlackBotChannel.objects.select_related('bot').filter(
            bot__is_active=True)

        for channel in channels:
            client = WebClient(token=channel.bot.bot_token)
            client.chat_postMessage(channel=channel.channel_id,
                                    attachments=message)
Ejemplo n.º 3
0
 def test_if_it_uses_custom_logger(self):
     logger = CustomLogger("test-logger")
     client = WebClient(
         base_url="http://localhost:8888",
         token="xoxb-api_test",
         logger=logger,
     )
     client.chat_postMessage(channel="C111", text="hello")
     self.assertTrue(logger.called)
 def test_blocks_without_text_arg(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     with self.assertWarns(UserWarning):
         resp = client.chat_postMessage(channel="C111", blocks=[])
     self.assertTrue(resp["ok"])
 def test_attachments_without_fallback(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     with self.assertWarns(UserWarning):
         resp = client.chat_postMessage(channel="C111", attachments=[{}])
     self.assertTrue(resp["ok"])
 def test_blocks_as_deserialzed_json_without_text_arg(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     # this generates a warning because "text" is missing
     with self.assertWarns(UserWarning):
         resp = client.chat_postMessage(channel="C111", attachments=json.dumps([]))
     self.assertTrue(resp["ok"])
 def test_blocks_as_deserialized_json_with_text_arg(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     # this DOESN'T warn because the "text" arg is present
     resp = client.chat_postMessage(
         channel="C111", text="test", blocks=json.dumps([])
     )
     self.assertTrue(resp["ok"])
Ejemplo n.º 8
0
def per_request():
    try:
        client = WebClient(token=os.environ["SLACK_BOT_TOKEN"], run_async=False)
        response = client.chat_postMessage(
            channel="#random", text="You used a new WebClient for posting this message!"
        )
        return str(response)
    except SlackApiError as e:
        return make_response(str(e), 400)
 def test_attachments_without_fallback_with_text_arg(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     # this warns because each attachment should have its own fallback, even with "text"
     with self.assertWarns(UserWarning):
         resp = client.chat_postMessage(
             channel="C111", text="test", attachments=[{}]
         )
     self.assertTrue(resp["ok"])
Ejemplo n.º 10
0
 def test_triggers_replies_in_a_thread(self):
     client = WebClient()
     client.chat_postMessage = MagicMock()
     user = "******"
     channel = "channel"
     trigger_word = "help me"
     subject = LoggingBot(client, [trigger_word], [channel], [], [], [])
     handled = subject.handle_message(channel, user, trigger_word, ts="ts")
     self.assertTrue(handled)
     self.assertNotEqual(
         "", client.chat_postMessage.call_args.kwargs.get("thread_ts", ""))
Ejemplo n.º 11
0
    def test_ignores_unmonitored_channels(self):
        client = WebClient()
        client.chat_postMessage = MagicMock()

        subject = LoggingBot(client, [], ["MONITORED"], [], [], [])
        handled = subject.handle_message("NOT_MONITORED",
                                         "user",
                                         "text",
                                         bot_profile="bot_profile")
        self.assertFalse(handled)
        client.chat_postMessage.assert_not_called()
 def test_attachments_as_deserialzed_json_without_text_arg(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     # this still generates a warning because "text" is missing. The attachment has already
     # been deserialized, which isn't explicitly prohibited in the docs (but isn't recommended)
     with self.assertWarns(UserWarning):
         resp = client.chat_postMessage(
             channel="C111", attachments=json.dumps([{"fallback": "test"}])
         )
     self.assertTrue(resp["ok"])
Ejemplo n.º 13
0
 def test_triggers_does_not_trigger_in_threads(self):
     client = WebClient()
     client.chat_postMessage = MagicMock()
     user = "******"
     channel = "channel"
     trigger_word = "help me"
     subject = LoggingBot(client, [trigger_word], [channel], [], [], [])
     handled = subject.handle_message(channel,
                                      user,
                                      trigger_word,
                                      thread_ts="ts")
     self.assertFalse(handled)
     client.chat_postMessage.assert_not_called()
Ejemplo n.º 14
0
    def test_ignores_bot_messages(self):
        client = WebClient()
        client.chat_postMessage = MagicMock()
        logging.debug = MagicMock()

        subject = LoggingBot(client, [], [], [], [], [])
        handled = subject.handle_message("channel",
                                         "user",
                                         "text",
                                         bot_profile="bot_profile")
        self.assertFalse(handled)
        client.chat_postMessage.assert_not_called()
        logging.debug.assert_called_with(AnyStringWith("bot"))
Ejemplo n.º 15
0
    def test_ignores_admin_messages(self):
        client = WebClient()
        client.chat_postMessage = MagicMock()
        logging.debug = MagicMock()

        user = "******"
        trigger_word = "triggered!"
        channel = "channel_8"

        subject = LoggingBot(client, [trigger_word], [channel], [], [user], [])
        handled = subject.handle_message(channel, user, "text")
        self.assertFalse(handled)
        client.chat_postMessage.assert_not_called()
        logging.debug.assert_called_with(AnyStringWith("admin"))
Ejemplo n.º 16
0
class TestRTMClient(unittest.TestCase):
    """Runs integration tests with real Slack API

    https://github.com/slackapi/python-slack-sdk/issues/605
    """
    def setUp(self):
        self.logger = logging.getLogger(__name__)
        self.bot_token = os.environ[SLACK_SDK_TEST_CLASSIC_APP_BOT_TOKEN]
        self.channel_id = os.environ[SLACK_SDK_TEST_RTM_TEST_CHANNEL_ID]
        self.rtm_client = RTMClient(token=self.bot_token, run_async=False)

    def tearDown(self):
        # Reset the decorators by @RTMClient.run_on
        RTMClient._callbacks = collections.defaultdict(list)

    @pytest.mark.skipif(condition=is_not_specified(),
                        reason="To avoid rate_limited errors")
    def test_issue_605(self):
        self.text = "This message was sent to verify issue #605"
        self.called = False

        @RTMClient.run_on(event="message")
        def process_messages(**payload):
            self.logger.info(payload)
            self.called = True

        def connect():
            self.logger.debug("Starting RTM Client...")
            self.rtm_client.start()

        t = threading.Thread(target=connect)
        t.daemon = True
        try:
            t.start()
            self.assertFalse(self.called)

            time.sleep(3)

            self.web_client = WebClient(
                token=self.bot_token,
                run_async=False,
            )
            new_message = self.web_client.chat_postMessage(
                channel=self.channel_id, text=self.text)
            self.assertFalse("error" in new_message)

            time.sleep(5)
            self.assertTrue(self.called)
        finally:
            t.join(0.3)
Ejemplo n.º 17
0
def send_slack_message(message, channel):
    """
    Use slack api to send a message to the desired channel
    """
    slack_web_client = WebClient(token=settings.SLACK_SDK_OAUTH_TOKEN)
    response = slack_web_client.chat_postMessage(
        channel=channel,
        username=settings.SLACK_USERNAME,
        icon_emoji=':robot_face:',
        text=message,
    )
    if not response.status_code == 200 or response.data.get('ok') is not True:
        # Here there should be code to manage errors, like logs, etc.
        pass

    return response
Ejemplo n.º 18
0
    def test_triggers_trigger_words(self):
        client = WebClient()
        client.chat_postMessage = MagicMock()

        user = "******"
        channel = "channel"
        trigger_words = ["help me"]

        for msg, should_handle in [("good morning", False), ("help", False),
                                   ("help me", True)]:
            subject = LoggingBot(client, trigger_words, [channel], [], [], [])

            handled = subject.handle_message(channel, user, msg, ts="ts")
            self.assertEqual(should_handle, handled, msg="Message=%s" % msg)

            if handled:
                self.assertEqual(
                    user, client.chat_postMessage.call_args.kwargs.get("user"))
Ejemplo n.º 19
0
def per_request_async():
    try:
        # This is not optimal and the host should have a large number of FD (File Descriptor)
        loop_for_this_request = asyncio.new_event_loop()

        async_client = WebClient(
            token=os.environ["SLACK_BOT_TOKEN"],
            run_async=True,
            loop=loop_for_this_request,
        )
        future = async_client.chat_postMessage(
            channel="#random",
            text="You used the singleton WebClient for posting this message!",
        )
        response = loop_for_this_request.run_until_complete(future)
        return str(response)
    except SlackApiError as e:
        return make_response(str(e), 400)
Ejemplo n.º 20
0
def start_onboarding(user_id: str, channel: str, client: WebClient):
    # Create a new onboarding tutorial.
    onboarding_tutorial = OnboardingTutorial(channel)

    # Get the onboarding message payload
    message = onboarding_tutorial.get_message_payload()

    # Post the onboarding message in Slack
    response = client.chat_postMessage(**message)

    # Capture the timestamp of the message we've just posted so
    # we can use it to update the message after a user
    # has completed an onboarding task.
    onboarding_tutorial.timestamp = response["ts"]

    # Store the message sent in onboarding_tutorials_sent
    if channel not in onboarding_tutorials_sent:
        onboarding_tutorials_sent[channel] = {}
    onboarding_tutorials_sent[channel][user_id] = onboarding_tutorial
Ejemplo n.º 21
0
    def test_executes_commands_in_channels(self):
        client = WebClient()
        client.chat_postMessage = MagicMock()

        channel = "channel"
        subject = LoggingBot(client, [], [channel], [], [], [])

        # choose the first command
        cmd = list(consts.COMMANDS.keys())[0]
        user = "******"

        handled = subject.handle_message(channel, user, cmd, ts="ts")
        self.assertTrue(handled)

        # because we did not supply a thread_ts to handle_message that
        # indicates the message was NOT within an existing thread so we should
        # not see a thread_ts (which means post in the original channel)
        thread_ts = client.chat_postMessage.call_args.kwargs.get("thread_ts")
        self.assertFalse(thread_ts)
Ejemplo n.º 22
0
class SlackService:
    def __init__(self):
        self.slack_bot_token = get_env('SLACK_BOT_TOKEN')
        self.slack_signing_secret = get_env('SLACK_SIGNING_SECRET')
        self.slack_web = WebClient(token=self.slack_bot_token)

    def start_event_service(self, flask_app):
        slack_event = SlackEventAdapter(self.slack_signing_secret,
                                        "/slack/events", flask_app)

    def post_notification(self, ticket_data):
        block_types = SlackBlockTypes()

        method = ticket_data["method"]

        # Cycle through possible notification methods
        # Send JSON payload respective to the notification method
        if method == "CREATE_TICKET":
            blocks = block_types.create_ticket_block(ticket_data)
            message = ticket_data[
                "username"] + " Created a Ticket :spiral_note_pad:"
        elif method == "PICKUP_TICKET":
            blocks = block_types.pickup_ticket_block(ticket_data)
            message = ":heavy_check_mark: Ticket picked up by " + ticket_data[
                "username"]
        elif method == "ASSIGN_TICKET":
            blocks = block_types.assigned_ticket_block(ticket_data)
            message = ":heavy_check_mark: " + ticket_data[
                "username"] + " has been assigned to your ticket!"
        elif method == "STATUS_UPDATE":
            blocks = block_types.field_update_block(ticket_data, "status")
            message = ":heavy_check_mark: Ticket status updated in the UHDA!"
        elif method == "PRIORITY_UPDATE":
            blocks = block_types.field_update_block(ticket_data, "priority")
            message = ":heavy_check_mark: Ticket priority updated in the UHDA!"
        else:
            blocks = block_types.error_ticket_block()
            message = " :four: :zero: :four: "

        return self.slack_web.chat_postMessage(channel=ticket_data["channel"],
                                               text=message,
                                               blocks=blocks)
Ejemplo n.º 23
0
 def test_executes_commands_in_threads(self):
     client = WebClient()
     client.chat_postMessage = MagicMock()
     channel = "channel"
     subject = LoggingBot(client, [], [channel], [], [], [])
     # choose the first command
     cmd = list(consts.COMMANDS.keys())[0]
     user = "******"
     handled = subject.handle_message(channel,
                                      user,
                                      cmd,
                                      ts="ts",
                                      thread_ts="thread_ts")
     self.assertTrue(handled)
     # because we supplied a thread_ts to handle_message that indicates the
     # message was within an existing thread so we should see thread_ts
     # here.
     thread_ts = client.chat_postMessage.call_args.kwargs.get(
         "thread_ts", "")
     self.assertEqual("thread_ts", thread_ts)
Ejemplo n.º 24
0
 def test_executes_commands_for_admins(self):
     client = WebClient()
     client.chat_postMessage = MagicMock()
     channel = "channel"
     user = "******"
     subject = LoggingBot(client, [], [channel], [], [user], [])
     # choose the first command
     cmd = list(consts.COMMANDS.keys())[0]
     handled = subject.handle_message(channel,
                                      user,
                                      cmd,
                                      ts="ts",
                                      thread_ts="thread_ts")
     self.assertTrue(handled, "handled message")
     args = client.chat_postMessage.call_args.kwargs
     block = consts.COMMANDS[cmd].items()
     # block is the message text that gets added when the command is called
     for key, value in block:
         self.assertIn(key, args, "key=%s" % key)
         self.assertEqual(value, args[key],
                          "key=%s value=%s" % (key, value))
Ejemplo n.º 25
0
# ------------------
# Only for running this script here
import sys
from os.path import dirname

sys.path.insert(1, f"{dirname(__file__)}/../../..")
# ------------------

import logging

logging.basicConfig(level=logging.DEBUG)

# export SLACK_API_TOKEN=xoxb-***
# python3 integration_tests/samples/readme/sending_messages.py

import os
from slack_sdk.web import WebClient
from slack_sdk.errors import SlackApiError

client = WebClient(token=os.environ["SLACK_API_TOKEN"])

try:
    response = client.chat_postMessage(channel="#random", text="Hello world!")
    assert response["message"]["text"] == "Hello world!"
except SlackApiError as e:
    # You will get a SlackApiError if "ok" is False
    assert e.response["ok"] is False
    assert e.response["error"]  # str like 'invalid_auth', 'channel_not_found'
    print(f"Got an error: {e.response['error']}")
Ejemplo n.º 26
0
class TestRTMClient(unittest.TestCase):
    """Runs integration tests with real Slack API

    https://github.com/slackapi/python-slack-sdk/issues/701
    """
    def setUp(self):
        self.logger = logging.getLogger(__name__)
        self.bot_token = os.environ[SLACK_SDK_TEST_CLASSIC_APP_BOT_TOKEN]

    def tearDown(self):
        # Reset the decorators by @RTMClient.run_on
        RTMClient._callbacks = collections.defaultdict(list)

    # @pytest.mark.skipif(condition=is_not_specified(), reason="to avoid rate_limited errors")
    @pytest.mark.skip()
    def test_receiving_all_messages(self):
        self.rtm_client = RTMClient(token=self.bot_token,
                                    loop=asyncio.new_event_loop())
        self.web_client = WebClient(token=self.bot_token)

        self.call_count = 0

        @RTMClient.run_on(event="message")
        def send_reply(**payload):
            self.logger.debug(payload)
            web_client, data = payload["web_client"], payload["data"]
            web_client.reactions_add(channel=data["channel"],
                                     timestamp=data["ts"],
                                     name="eyes")
            self.call_count += 1

        def connect():
            self.logger.debug("Starting RTM Client...")
            self.rtm_client.start()

        rtm = threading.Thread(target=connect)
        rtm.daemon = True

        rtm.start()
        time.sleep(3)

        total_num = 10

        sender_completion = []

        def sent_bulk_message():
            for i in range(total_num):
                text = f"Sent by <https://slack.dev/python-slackclient/|python-slackclient>! ({i})"
                self.web_client.chat_postMessage(channel="#random", text=text)
                time.sleep(0.1)
            sender_completion.append(True)

        num_of_senders = 3
        senders = []
        for sender_num in range(num_of_senders):
            sender = threading.Thread(target=sent_bulk_message)
            sender.daemon = True
            sender.start()
            senders.append(sender)

        while len(sender_completion) < num_of_senders:
            time.sleep(1)

        expected_call_count = total_num * num_of_senders
        wait_seconds = 0
        max_wait = 20
        while self.call_count < expected_call_count and wait_seconds < max_wait:
            time.sleep(1)
            wait_seconds += 1

        self.assertEqual(total_num * num_of_senders, self.call_count,
                         "The RTM handler failed")

    @pytest.mark.skipif(condition=is_not_specified(),
                        reason="to avoid rate_limited errors")
    @async_test
    async def test_receiving_all_messages_async(self):
        self.rtm_client = RTMClient(token=self.bot_token, run_async=True)
        self.web_client = WebClient(token=self.bot_token, run_async=False)

        self.call_count = 0

        @RTMClient.run_on(event="message")
        async def send_reply(**payload):
            self.logger.debug(payload)
            web_client, data = payload["web_client"], payload["data"]
            await web_client.reactions_add(channel=data["channel"],
                                           timestamp=data["ts"],
                                           name="eyes")
            self.call_count += 1

        # intentionally not waiting here
        self.rtm_client.start()

        await asyncio.sleep(3)

        total_num = 10

        sender_completion = []

        def sent_bulk_message():
            for i in range(total_num):
                text = f"Sent by <https://slack.dev/python-slackclient/|python-slackclient>! ({i})"
                self.web_client.chat_postMessage(channel="#random", text=text)
                time.sleep(0.1)
            sender_completion.append(True)

        num_of_senders = 3
        senders = []
        for sender_num in range(num_of_senders):
            sender = threading.Thread(target=sent_bulk_message)
            sender.daemon = True
            sender.start()
            senders.append(sender)

        while len(sender_completion) < num_of_senders:
            await asyncio.sleep(1)

        expected_call_count = total_num * num_of_senders
        wait_seconds = 0
        max_wait = 20
        while self.call_count < expected_call_count and wait_seconds < max_wait:
            await asyncio.sleep(1)
            wait_seconds += 1

        self.assertEqual(total_num * num_of_senders, self.call_count,
                         "The RTM handler failed")
Ejemplo n.º 27
0
    # Post the onboarding message in Slack
    return local_message


def _flip_coin():
    """Flip a single coin"""
    rand_int = random.randint(0, 1)
    if rand_int == 0:
        results = "Heads"
    else:
        results = "Tails"

    text = f"The result is {results}"

    return text


if __name__ == "__main__":
    from slack_sdk.web import WebClient

    # Create a slack client
    slack_web_client = WebClient(token=os.environ.get("SLACK_TOKEN"))

    # Get a new CoinBot
    # coin_bot = CoinBot("#testing")
    message = flip_coin("U021L1T8MAT")

    # Post the onboarding message in slack
    slack_web_client.chat_postMessage(**message)
Ejemplo n.º 28
0
class SlackBot():
    def __init__(self, setting):
        xoxb_token = setting['slack']['xoxb_token']
        xapp_token = setting['slack']['xapp_token']
        self._web_client = WebClient(token=xoxb_token)
        self._sm_client = SocketModeClient(app_token=xapp_token,
                                           web_client=self._web_client)
        self.plugins_setting = setting['plugins']
        self.plugins_path = setting['bot']['plugins_dir']
        self.plugin_modules = []
        self.plugin_classes = []
        self.plugin_instances = []
        self._self = None
        self._team = None
        self._users_list = {}  # [ 'id' ] => SlackUser
        self._channels_list = {}
        self._data = None

    def _get_rtm_client(self):
        return self._rtm_client

    def _set_rtm_client(self, rc):
        self._rtm_client = rc

    rtm_client = property(_get_rtm_client, _set_rtm_client)

    def _get_web_client(self):
        return self._web_client

    def _set_web_client(self, rc):
        self._web_client = rc

    web_client = property(_get_web_client, _set_web_client)

    # plugin loader

    def load_plugins(self):
        for ps in self.plugins_setting:
            mod = importlib.import_module(ps['module'])
            klass_name = ps['name']
            klass = getattr(mod, klass_name)
            self.plugin_classes.append(klass)
            self.plugin_instances.append(klass(self, ps))

    def load_plugins_filename_based(self):
        plugins_dir = os.listdir(self.plugins_path)
        #        current_dir = os.path.dirname( os.path.abspath( __file__ ) )
        for filename in plugins_dir:
            if filename.endswith('.py'):
                if filename == "__init__.py":
                    continue
                klass_name = os.path.splitext(filename)[0]
                klass_name = klass_name[0].upper() + klass_name[1:]
                modulePath = self.plugins_path + '/' + filename
                cpath = os.path.splitext(modulePath)[0].replace(
                    os.path.sep, '.')
                try:
                    mod = importlib.import_module(cpath)
                    self.plugin_modules.append(mod)
                    klass = getattr(mod, klass_name)
                    self.plugin_classes.append(klass)
                    self.plugin_instances.append(klass(self, klass_name))
                except ModuleNotFoundError:
                    print('Module not found')
                except AttributeError:
                    print('Method not found')

    def unload_plugins(self):
        for ins in self.plugin_instances:
            del (ins)
        self.plugin_instances = []

        for cls in self.plugin_classes:
            del (cls)
        self.plugin_classes = []

        for mod in self.plugin_modules:
            del (mod)
        self.plugin_modules = []

    def reload_plugins(self):
        self.unload_plugins()
        self.load_plugins()

    # bot information

    def self_user(self):
        return self._self

    def self_id(self):
        u = self.self_user()
        return u.id

    def self_name(self):
        return self.self_user().name

    def team_info(self):
        return self._team

    def team_id(self):
        return self.team_info()['id']

    def team_name(self):
        return self.team_info()['name']

    def update_self_user(self, user):
        self._self = user

    def update_team_info(self, info):
        self._team = info

    def update_users_list(self, users):
        for user in users:
            self._users_list[user['id']] = SlackUser(user)

    def update_groups_list(self, groups):
        for group in groups:
            self._channels_list[group['id']] = SlackGroup(group)

    def update_ims_list(self, ims):
        for im in ims:
            self._channels_list[im['id']] = SlackIM(im)

    def update_channels_list(self, channels):
        for channel in channels:
            self._channels_list[channel['id']] = SlackChannel(channel)

    def resolve_channel_id_from_name(self, name):
        pass

    # plugin commands

    def send_message(self, channel, message, attachments_json=None):
        self._web_client.chat_postMessage(channel=channel.id,
                                          text=message,
                                          attachments=attachments_json)

    def send_mention_message(self,
                             channel,
                             user,
                             message,
                             attachments_json=None):
        mention_message = "<@" + user.id + "> " + message
        self._web_client.chat_postMessage(channel=channel.id,
                                          text=mention_message,
                                          attachments=attachments_json)

    def send_kick(self, channel, user):
        self._web_client.channels_kick(channel=channel.id, user=user.id)

    # plugin events

    def on_server_connect(self):
        for plugin in self.plugin_instances:
            plugin.on_server_connect()

    def process_message(self, data):
        channel = self._channels_list[data['channel']]
        user = self._users_list[data['user']]
        text = data['text']
        #        if user.id != self.self_id(): # ignore own message
        for plugin in self.plugin_instances:
            plugin.on_message(channel, user, text)

    def process_message_changed(self, data):
        channel = self._channels_list[data['channel']]
        user = self._users_list[data['message']['user']]
        text = data['message']['text']
        prev_user = data['previous_message']['user']
        prev_text = data['previous_message']['text']
        #        if user.id != self.self_id(): # ignore own message
        for plugin in self.plugin_instances:
            plugin.on_message_changed(channel, user, text, prev_user,
                                      prev_text)

    def on_message(self, payload):
        data = payload
        if 'bot_id' in data:
            return
        if 'subtype' in data:
            if data['subtype'] == 'message_changed':
                self.process_message_changed(data)
        else:
            self.process_message(data)

    def on_channel_joined(self, **payload):
        data = payload
        channel = data['channel']
        self._channels_list[channel['id']] = SlackChannel(channel)

    def on_channel_left(self, **payload):
        data = payload
        del self._channels_list[data['channel']]
        # TODO: It should be not delete the channel and It must be update the status such as a 'is_member'.
        # self._channels_list[ data[ 'channel' ] ].is_member = False

    def on_member_joined_channel(self, **payload):
        data = payload
        channel = self._channels_list[data['channel']]
        user = self._users_list[data['user']]
        for plugin in self.plugin_instances:
            plugin.on_joined(channel, user)

    def on_member_left_channel(self, **payload):
        data = payload
        channel = self._channels_list[data['channel']]
        user = self._users_list[data['user']]
        for plugin in self.plugin_instances:
            plugin.on_left(channel, user)

    # process slack rtm

    def on_socket_mode_request(self, client: SocketModeClient,
                               req: SocketModeRequest):
        if req.type == "events_api":
            # Acknowledge the request anyway
            response = SocketModeResponse(envelope_id=req.envelope_id)
            client.send_socket_mode_response(response)

            if req.payload['event']['type'] == 'open':
                self.on_open(req.payload['event'])
            elif req.payload['event']['type'] == 'message':
                self.on_message(req.payload['event'])
            elif req.payload['event']['type'] == 'channel_joined':
                self.on_channel_joined(req.payload['event'])
            elif req.payload['event']['type'] == 'channel_left':
                self.on_channel_left(req.payload['event'])
            elif req.payload['event']['type'] == 'member_joined_channel':
                self.on_member_joined_channel(req.payload['event'])
            elif req.payload['event']['type'] == 'member_left_channel':
                self.on_member_left_channel(req.payload['event'])

    def start(self):
        self._sm_client.socket_mode_request_listeners.append(
            self.on_socket_mode_request)
        self._sm_client.connect()

        response = self._web_client.users_list()
        self.update_users_list(response['members'])

        response = self._web_client.conversations_list()
        self.update_channels_list(response['channels'])

        response = self._web_client.team_info()
        self.update_team_info(response['team'])

        response = self._web_client.auth_test()
        self_id = response['user_id']
        self.update_self_user(self._users_list[self_id])

        self.load_plugins()
        self.on_server_connect()

        from threading import Event
        Event().wait()
 def test_text_arg_only(self):
     client = WebClient(
         base_url="http://localhost:8888", token="xoxb-api_test", team_id="T111"
     )
     resp = client.chat_postMessage(channel="C111", text="test")
     self.assertTrue(resp["ok"])
Ejemplo n.º 30
0
sys.path.insert(1, f"{dirname(__file__)}/../../..")
# ------------------

import logging

logging.basicConfig(level=logging.DEBUG)

# export SLACK_API_TOKEN=xoxb-***
# python3 integration_tests/samples/basic_usage/emoji_reactions.py

import os
from slack_sdk.web import WebClient

client = WebClient(token=os.environ["SLACK_API_TOKEN"])

if __name__ == "__main__":
    channel_id = "#random"
    user_id = client.users_list()["members"][0]["id"]
else:
    channel_id = "C0XXXXXX"
    user_id = "U0XXXXXXX"

response = client.chat_postMessage(channel=channel_id, text="Give me some reaction!")
# Ensure the channel_id is not a name
channel_id = response["channel"]
ts = response["message"]["ts"]

response = client.reactions_add(channel=channel_id, name="thumbsup", timestamp=ts)

response = client.reactions_remove(channel=channel_id, name="thumbsup", timestamp=ts)