cohit's picture
Upload folder using huggingface_hub
0827183 verified
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import json
import urllib.parse
from aiohttp.web_request import Request
from aiohttp.web_response import Response
from slack.web.classes.attachments import Attachment
from botbuilder.schema import (
Activity,
ConversationAccount,
ChannelAccount,
ActivityTypes,
)
from .slack_message import SlackMessage
from .slack_client import SlackClient
from .slack_event import SlackEvent
from .slack_payload import SlackPayload
from .slack_request_body import SlackRequestBody
class SlackHelper:
@staticmethod
def activity_to_slack(activity: Activity) -> SlackMessage:
"""
Formats a BotBuilder Activity into an outgoing Slack message.
:param activity: A BotBuilder Activity object.
:type activity: :class:`botbuilder.schema.Activity`
:return: A Slack message object with {text, attachments, channel, thread ts} and any fields found in
activity.channelData.
:rtype: :class:`SlackMessage`
"""
if not activity:
raise Exception("Activity required")
# use ChannelData if available
if activity.channel_data:
message = activity.channel_data
else:
message = SlackMessage(
ts=activity.timestamp,
text=activity.text,
channel=activity.conversation.id,
)
if activity.attachments:
attachments = []
for att in activity.attachments:
if att.name == "blocks":
message.blocks = att.content
else:
new_attachment = Attachment(
author_name=att.name,
thumb_url=att.thumbnail_url,
text="",
)
attachments.append(new_attachment)
if attachments:
message.attachments = attachments
if (
activity.conversation.properties
and "thread_ts" in activity.conversation.properties
):
message.thread_ts = activity.conversation.properties["thread_ts"]
if message.ephemeral:
message.user = activity.recipient.id
if (
message.icon_url
or not (message.icons and message.icons.status_emoji)
or not message.username
):
message.as_user = False
return message
@staticmethod
def response( # pylint: disable=unused-argument
req: Request, code: int, text: str = None, encoding: str = None
) -> Response:
"""
Formats an aiohttp Response.
:param req: The original aiohttp Request.
:type req: :class:`aiohttp.web_request.Request`
:param code: The HTTP result code to return.
:type code: int
:param text: The text to return.
:type text: str
:param encoding: The text encoding. Defaults to UTF-8.
:type encoding: str
:return: The aoihttp Response
:rtype: :class:`aiohttp.web_response.Response`
"""
response = Response(status=code)
if text:
response.content_type = "text/plain"
response.body = text.encode(encoding=encoding if encoding else "utf-8")
return response
@staticmethod
def payload_to_activity(payload: SlackPayload) -> Activity:
"""
Creates an activity based on the Slack event payload.
:param payload: The payload of the Slack event.
:type payload: :class:`SlackPayload`
:return: An activity containing the event data.
:rtype: :class:`botbuilder.schema.Activity`
"""
if not payload:
raise Exception("payload is required")
activity = Activity(
channel_id="slack",
conversation=ConversationAccount(id=payload.channel["id"], properties={}),
from_property=ChannelAccount(
id=(
payload.message.bot_id
if payload.message.bot_id
else payload.user["id"]
)
),
recipient=ChannelAccount(),
channel_data=payload,
text=None,
type=ActivityTypes.event,
value=payload,
)
if payload.thread_ts:
activity.conversation.properties["thread_ts"] = payload.thread_ts
if payload.actions:
action = payload.actions[0]
if action["type"] == "button":
activity.text = action["value"]
elif action["type"] == "select":
selected_option = action["selected_options"]
activity.text = selected_option["value"] if selected_option else None
elif action["type"] == "static_select":
activity.text = action["selected_options"]["value"]
if activity.text:
activity.type = ActivityTypes.message
return activity
@staticmethod
async def event_to_activity(event: SlackEvent, client: SlackClient) -> Activity:
"""
Creates an activity based on the Slack event data.
:param event: The data of the Slack event.
:type event: :class:`SlackEvent`
:param client: The Slack client.
:type client: :class:`SlackClient`
:return: An activity containing the event data.
:rtype: :class:`botbuilder.schema.Activity`
"""
if not event:
raise Exception("slack event is required")
activity = Activity(
id=event.event_ts,
channel_id="slack",
conversation=ConversationAccount(
id=event.channel if event.channel else event.channel_id, properties={}
),
from_property=ChannelAccount(
id=event.bot_id if event.bot_id else event.user_id
),
recipient=ChannelAccount(id=None),
channel_data=event,
text=event.text,
type=ActivityTypes.event,
)
if not activity.conversation.id:
if event.item and event.item_channel:
activity.conversation.id = event.item_channel
else:
activity.conversation.id = event.team
activity.recipient.id = await client.get_bot_user_identity(activity=activity)
if event.thread_ts:
activity.conversation.properties["thread_ts"] = event.thread_ts
if event.type == "message" and not event.subtype and not event.bot_id:
if not event.subtype:
activity.type = ActivityTypes.message
activity.text = event.text
activity.conversation.properties["channel_type"] = event.channel_type
activity.value = event
else:
activity.name = event.type
activity.value = event
return activity
@staticmethod
async def command_to_activity(
body: SlackRequestBody, client: SlackClient
) -> Activity:
"""
Creates an activity based on a Slack event related to a slash command.
:param body: The data of the Slack event.
:type body: :class:`SlackRequestBody`
:param client: The Slack client.
:type client: :class:`SlackClient`
:return: An activity containing the event data.
:rtype: :class:`botbuilder.schema.Activity`
"""
if not body:
raise Exception("body is required")
activity = Activity(
id=body.trigger_id,
channel_id="slack",
conversation=ConversationAccount(id=body.channel_id, properties={}),
from_property=ChannelAccount(id=body.user_id),
recipient=ChannelAccount(id=None),
channel_data=body,
text=body.text,
type=ActivityTypes.event,
name="Command",
value=body.command,
)
activity.recipient.id = await client.get_bot_user_identity(activity)
activity.conversation.properties["team"] = body.team_id
return activity
@staticmethod
def query_string_to_dictionary(query: str) -> {}:
"""
Converts a query string to a dictionary with key-value pairs.
:param query: The query string to convert.
:type query: str
:return: A dictionary with the query values.
:rtype: :class:`typing.Dict`
"""
values = {}
if not query:
return values
pairs = query.replace("+", "%20").split("&")
for pair in pairs:
key_value = pair.split("=")
key = key_value[0]
value = urllib.parse.unquote(key_value[1])
values[key] = value
return values
@staticmethod
def deserialize_body(content_type: str, request_body: str) -> SlackRequestBody:
"""
Deserializes the request's body as a SlackRequestBody object.
:param content_type: The content type of the body.
:type content_type: str
:param request_body: The body of the request.
:type request_body: str
:return: A SlackRequestBody object.
:rtype: :class:`SlackRequestBody`
"""
if not request_body:
return None
if content_type == "application/x-www-form-urlencoded":
request_dict = SlackHelper.query_string_to_dictionary(request_body)
elif content_type == "application/json":
request_dict = json.loads(request_body)
else:
raise Exception("Unknown request content type")
if "command=%2F" in request_body:
return SlackRequestBody(**request_dict)
if "payload=" in request_body:
payload = SlackPayload(**request_dict)
return SlackRequestBody(payload=payload, token=payload.token)
return SlackRequestBody(**request_dict)