Beispiel #1
0
async def slack_client(app: web.Application) -> AsyncGenerator[None, None]:
    slack = SlackAPI(token=app["SLACK_TOKEN"], session=app["client_session"])
    _register_in_app(app, "slack_client", slack)

    slack_legacy = SlackAPI(token=app["SLACK_INVITE_TOKEN"], session=app["client_session"])
    _register_in_app(app, "slack_client_legacy", slack_legacy)

    yield
Beispiel #2
0
async def _cleanup_user(app, user):
    try:
        async with app["plugins"]["pg"].connection() as pg_con:
            messages = await pg_con.fetch(
                """SELECT id, channel FROM slack.messages WHERE "user" = $1""",
                user)

        api = SlackAPI(session=app["http_session"],
                       token=os.environ["SLACK_ADMIN_TOKEN"])
        for message in messages:
            try:
                data = {"channel": message["channel"], "ts": message["id"]}
                await api.query(url=methods.CHAT_DELETE, data=data)
            except SlackAPIError as e:
                if e.error == "message_not_found":
                    continue
                else:
                    LOG.exception(
                        "Failed to cleanup message %s in channel %s",
                        message["id"],
                        message["channel"],
                    )
            except Exception:
                LOG.exception(
                    "Failed to cleanup message %s in channel %s",
                    message["id"],
                    message["channel"],
                )
    except Exception:
        LOG.exception("Unexpected exception cleaning up user %s", user)
Beispiel #3
0
    def __init__(self, loop, config_file: str = "config.yaml"):
        self.loop = loop
        self.config = Config.from_file(config_file)

        self.session = ClientSession()
        self.slack_client = SlackAPI(token=self.config.bot_token,
                                     session=self.session)
        self.waiters = []

        self.commands = self.config.commands
        self.prefix = self.config.prefix
        self.command_types = {
            "get_id": self.get_id,
            "read_web": self.read_web,
            "run_cmd": self.run_cmd
        }
Beispiel #4
0
    def load(self, sirbot):
        LOG.info("Loading slack plugin")
        self.api = SlackAPI(session=sirbot.http_session, token=self.token)

        sirbot.router.add_route("POST", "/slack/events",
                                endpoints.incoming_event)
        sirbot.router.add_route("POST", "/slack/commands",
                                endpoints.incoming_command)
        sirbot.router.add_route("POST", "/slack/actions",
                                endpoints.incoming_action)

        if self.bot_user_id and not self.bot_id:
            sirbot.on_startup.append(self.find_bot_id)
Beispiel #5
0

async def iterate(client):

    async for channel in client.iter(slack.methods.CHANNELS_LIST, limit=4):
        pprint.pprint(channel)


if __name__ == "__main__":

    if len(sys.argv) > 1:
        TOKEN = sys.argv[1]
    else:
        TOKEN = os.environ.get("SLACK_TOKEN")

    if not TOKEN:
        raise ValueError("No slack token provided !")

    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession(loop=loop)
    slack_client = SlackAPI(token=TOKEN,
                            session=session,
                            raise_on_rate_limit=True)

    try:
        loop.run_until_complete(iterate(slack_client))
    except KeyboardInterrupt:
        pass

    loop.run_until_complete(session.close())
Beispiel #6
0
            asyncio.ensure_future(respond_to_message(event, client))


async def respond_to_message(message, client):
    response = message.response()
    response['text'] = 'Hello world !'
    await client.query(slack.methods.CHAT_POST_MESSAGE,
                       data=response.serialize())


if __name__ == '__main__':

    if len(sys.argv) > 1:
        TOKEN = sys.argv[1]
    else:
        TOKEN = os.environ.get('SLACK_TOKEN')

    if not TOKEN:
        raise ValueError('No slack token provided !')

    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession(loop=loop)
    slack_client = SlackAPI(token=TOKEN, session=session)

    try:
        loop.run_until_complete(rtm(slack_client))
    except KeyboardInterrupt:
        pass

    loop.run_until_complete(session.close())
Beispiel #7
0
async def slack_client(app: web.Application) -> AsyncGenerator[None, None]:
    app["slack_client"] = SlackAPI(token=app["slack_token"],
                                   session=app["client_session"])
    app["slack_client_legacy"] = SlackAPI(token=app["slack_invite_token"],
                                          session=app["client_session"])
    yield
Beispiel #8
0
class SlackBot:
    def __init__(self, loop, config_file: str = "config.yaml"):
        self.loop = loop
        self.config = Config.from_file(config_file)

        self.session = ClientSession()
        self.slack_client = SlackAPI(token=self.config.bot_token,
                                     session=self.session)
        self.waiters = []

        self.commands = self.config.commands
        self.prefix = self.config.prefix
        self.command_types = {
            "get_id": self.get_id,
            "read_web": self.read_web,
            "run_cmd": self.run_cmd
        }

    async def run(self):
        print("Running")
        await self.rtm()

    async def get_id(self, command, message: Message):
        text = message["text"]
        mentioned_ids = re.findall(mention, text)
        await self.send_message(message["channel"], " ".join(mentioned_ids))

    async def read_web(self, command, message: Message):
        async with self.session.get(command["url"]) as resp:
            resp = await resp.text()
        await self.send_message(message["channel"], resp)

    async def run_cmd(self, command, message: Message):
        output = subprocess.run(command["cmd"],
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        if command["display_output"]:
            resp = (f"```\n{output.stdout.decode().strip()}\n```" if output.stdout else "") + \
                   (f"```\n{output.stderr.decode().strip()}\n```" if output.stderr else "")
            await self.send_message(message["channel"], resp)

    async def run_command(self, command, message: Message):
        """
        Run a command after checking permissions.
        """
        channel = message["channel"]
        if "acl1" in command:
            if not command["acl1"] or message["user"] not in command["acl1"]:
                return await self.send_message(
                    channel, "You are not in the acl list for this command.")
        if "reply1" in command:
            await self.send_message(channel, command["reply1"])
        if "acl2" in command and command["acl2"]:
            message2 = await self.wait_for_message(
                f"{self.prefix}{command['trigger2']}",
                timeout=command["timeout"])
            if message2 is None:
                return await self.send_message(channel, "Timed out.")
            if message2["user"] not in command["acl2"]:
                return await self.send_message(
                    channel, "You are not in the acl list for this command.")
            if message2["user"] == message["user"]:
                return await self.send_message(
                    channel,
                    "The authorising user cannot be the initiating user.")
            if "reply2" in command:
                await self.send_message(channel, command["reply2"])

        await self.command_types[command["type"]](command, message)

        if "complete" in command:
            await self.send_message(channel, command["complete"])

    async def wait_for_message(self, text: str, timeout: int) -> Message:
        """
        Wait until receive a message `text` within `timeout`.
        Returns None if timed out or the message.
        """
        future = loop.create_future()
        check = lambda event: event.event["text"] == text
        self.waiters.append((future, check))
        try:
            event = await asyncio.wait_for(future, timeout=timeout)
        except asyncio.TimeoutError:
            return None
        return event

    async def send_message(self, channel: str, message: str):
        """
        Send `message` to `channel`
        """
        await self.slack_client.query(slack.methods.CHAT_POST_MESSAGE,
                                      data={
                                          "channel": channel,
                                          "text": message,
                                      })

    async def rtm(self):
        """
        Main loop, parses Slack messages and runs them
        """
        async for event in self.slack_client.rtm():
            if isinstance(event, Message):
                for future, check in self.waiters:
                    if check(event):
                        future.set_result(event)

                if not event.event["text"].startswith(self.prefix):
                    continue
                command = event.event["text"].replace(self.prefix, "",
                                                      1).split(" ", 1)[0]
                if command in self.commands:
                    asyncio.ensure_future(
                        self.run_command(self.commands[command], event.event))
Beispiel #9
0
    def __init__(self):
        super(SlackHandler, self).__init__()
        session = ClientSession()
        self.slack_client = SlackAPI(token=None, session=session)

        self.channels = WeakValueDictionary()
Beispiel #10
0
class SlackHandler(GenericHandler):
    def __init__(self):
        super(SlackHandler, self).__init__()
        session = ClientSession()
        self.slack_client = SlackAPI(token=None, session=session)

        self.channels = WeakValueDictionary()

    async def setup(self, token):
        self.slack_client._token = token
        await self.update_team_info()
        await self.update_channels()
        asyncio.ensure_future(self.rtm())
        print("Logged into Slack")

    def get_channel(self, serialised) -> Optional[SlackChannel]:
        channel_id = serialised["id"]
        try:
            return self.channels[channel_id]
        except KeyError:
            pass
        rtn = SlackChannel(channel_id, self.slack_client)
        self.channels[channel_id] = rtn
        return rtn

    async def rtm(self):
        async for event in self.slack_client.rtm():
            if isinstance(event, Message):
                await asyncio.gather(*[channel.on_message_handler(event) for channel in self.channels.values()])
            if isinstance(event, Event):
                if event["type"].startswith("channel_"):
                    await self.update_channels()

    @property
    def serialised_channels(self):
        return self._serialised_channels

    async def update_channels(self):
        channels = await self.slack_client.query(
            slack.methods.CONVERSATIONS_LIST,
            data={
                "exclude_archived": True
            }
        )
        self._serialised_channels = [
            {
                "type": "slack",
                "id": channel["id"],
                "name": channel["name"],
                "server": self.team_info
            }
            for channel in channels["channels"]
            if channel["is_member"]
        ]
    
    async def update_team_info(self):
        team_info = await self.slack_client.query("https://slack.com/api/team.info")
        self.team_info = {
            "id": team_info["team"]["id"],
            "name": team_info["team"]["name"],
            "icon": team_info["team"]["icon"]["image_132"]
        }
Beispiel #11
0
    def initBot(self, bot: BotType, token: str) -> Deferred:
        self.slack_client[bot] = SlackAPI(token=token, session=self.session)

        return as_deferred(self._setup(bot))