使用包含上传图像的 Slack WebClient 发送消息

Sending message with Slack WebClient that includes an uploading image

我正在尝试使用 Slack Web 客户端将消息从机器人发送到私人频道。该消息将包括一些文本和图像。阅读当前的 Slack 文档后,完成此操作的最佳方法似乎是使用 file.upload 方法将文件上传到 Slack,然后使用 chat.PostMessage 方法发送消息,包括URL 到托管图像。虽然我似乎可以上传文件,但当我发送消息时,我收到有关我上传的文件的错误消息。我不确定我是否传递了错误的 URL 或上传图片后是否还需要做其他事情。我能够在没有文件的情况下成功发送消息,所以我知道问题与图片有关。

Error: The request to the Slack API failed.
The server responded with: {'ok': False, 'error': 'invalid_blocks', 'errors': ['downloading image failed [json-pointer:/blocks/1/image_url]'], 'response_metadata': {'messages': ['[ERROR] downloading image failed [json-pointer:/blocks/1/image_url]']}}

下面是我用来创建 Web 客户端、上传文件然后发送消息的过程。

import os
import requests
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from pprint import pprint

# create Slack web client
client = WebClient(token="xoxb-123456789")

# find the IDs of the Slack channels
for result in client.conversations_list():
    for channel in result["channels"]:
        if channel['name'] == 'my_channel':
            channel_id = channel['id']
            break

# upload image to my Slack channel
image = client.files_upload(
    channel = channel_id,
    initial_comment = "This is my image",
    file = "~/image.png"
)

# write my message
block = [
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "Guess what?  I don't know"
            }
    },
    {
            "type": "image",
            "image_url": image['file']['permalink'],
            "alt_text": "inspiration"
    } 
]

# try to send message with image
try:
    result = client.chat_postMessage(
        channel = channel_id,
        text = "New message for you",
        blocks = block
    )
    
except SlackApiError as e:
    print(f"Error: {e}")

此时,我遇到以下错误消息:

Error: The request to the Slack API failed.
The server responded with: {'ok': False, 'error': 'invalid_blocks', 'errors': ['downloading image failed [json-pointer:/blocks/1/image_url]'], 'response_metadata': {'messages': ['[ERROR] downloading image failed [json-pointer:/blocks/1/image_url]']}}

为了排除故障,这是我取回的数据

# print the details about the file uploaded
pprint(image['file'])

{'channels': [],
 'comments_count': 0,
 'created': 1648070852,
 'display_as_bot': False,
 'editable': False,
 'external_type': '',
 'filetype': 'png',
 'groups': [],
 'has_rich_preview': False,
 'id': 'FHBB87462378',
 'ims': [],
 'is_external': False,
 'is_public': False,
 'is_starred': False,
 'media_display_type': 'unknown',
 'mimetype': 'image/png',
 'mode': 'hosted',
 'name': 'image.png',
 'original_h': 1004,
 'original_w': 1790,
 'permalink': 'https://sandbox.enterprise.slack.com/files/123456789/ABC/image.png',
 'permalink_public': 'https://slack-files.com/123456789',
 'pretty_type': 'PNG',
 'public_url_shared': False,
 'shares': {},
 'size': 1623063,
 'thumb_1024': 'https://files.slack.com/files-tmb/123456789/image_1024.png',
 'thumb_1024_h': 574,
 'thumb_1024_w': 1024,
 'thumb_160': 'https://files.slack.com/files-tmb/123456789/image_160.png',
 'thumb_360': 'https://files.slack.com/files-tmb/123456789/image_360.png',
 'thumb_360_h': 202,
 'thumb_360_w': 360,
 'thumb_480': 'https://files.slack.com/files-tmb/123456789/image_480.png',
 'thumb_480_h': 269,
 'thumb_480_w': 480,
 'thumb_64': 'https://files.slack.com/files-tmb/123456789/image_64.png',
 'thumb_720': 'https://files.slack.com/files-tmb/123456789/image_720.png',
 'thumb_720_h': 404,
 'thumb_720_w': 720,
 'thumb_80': 'https://files.slack.com/files-tmb/123456789/image_80.png',
 'thumb_800': 'https://files.slack.com/files-tmb/123456789/image_800.png',
 'thumb_800_h': 449,
 'thumb_800_w': 800,
 'thumb_960': 'https://files.slack.com/files-tmb/123456789/image_960.png',
 'thumb_960_h': 538,
 'thumb_960_w': 960,
 'thumb_tiny': 'AoinfgvoindwoidnasQOJWQNWOIQONQqoinoiQQ/2Q==',
 'timestamp': 1648070852,
 'title': 'image',
 'url_private': 'https://files.slack.com/files-pri/123456789/image.png',
 'url_private_download': 'https://files.slack.com/files-pri/123456789/download/image.png',
 'user': 'U123456789',
 'username': ''}

我不确定你为什么没有得到 KeyError,但看起来你使用的是 response["permalink_public"] 而不是 response["file"]["permalink_public"]。参见 Slack API:https://api.slack.com/methods/files.upload

image = client.files_upload(
    channel = channel_id,
    initial_comment = "This is my image",
    file = "~/image.png"
)

image_url = image["file"]["permalink"]

# alternatively
# image_url = image["file"]["permalink_public"]

block = [
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "Guess what?  I don't know"
            }
    },
    {
            "type": "image",
            "image_url": image_url,
            "alt_text": "inspiration"
    } 
]

我发现除了块之外,您还需要 top-level 文本 属性。下面的示例按预期工作,现在我可以将图像上传到 Slack 并将该图像包含在消息中。

有关详细信息,请参阅 https://github.com/slackapi/python-slack-sdk/issues/1194

# get the file URL
file_url = image["file"]["permalink"]

# write my message
block = [
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "Guess what?  I don't know"
            }
    }
]

# try to send message with image
try:
    result = client.chat_postMessage(
        channel = channel_id,
        text = f"Here is the image data that you want! {file_url}",
        blocks = block
    )
    
except SlackApiError as e:
    print(f"Error: {e}")