## 概要 [[Slack Web API]]で[[MP4]]ファイルなどの動画をスマートにアップロードする方法が、ドキュメントを見たり調べた限りだとよく分からない。事実を記録している。 ## 公式クライアントの挙動 mp4ファイルをD&Dしたときの挙動。 ### アップロード先URLの取得 ```http POST https://xxx.slack.com/api/files.getUploadURL?_x_id=99be626d-1712389821.855&_x_csid=fgNfxlapd2M&slack_route=TXXXXXXXX&_x_version_ts=1712363845&_x_frontend_build_type=current&_x_desktop_ia=4&_x_gantry=true&fp=92 ``` ```json { "ok": true, "file": "F06SP7J72JK", "upload_url": "https:\/\/files.slack.com\/upload\/v1\/CwABAAAAWAoAAdP0kn6O2wn5CgACF8OheGhrWvAMAAMLAAEAAAAJVDE5NENIWDhSCwACAAAACVUxREZFQlhWMwsAAwAAAAtGMDZTUDdKNzJKSwAKAAQAAAAAAAlEGAALAAIAAAAUdaTPph-EUtwh2fKDBE3b9sgM8c8A"} ``` ### アップロード ```http POST https://files.slack.com/upload/v1/CwABAAAAWAoAAdP0kn6O2wn5CgACF8OheGhrWvAMAAMLAAEAAAAJVDE5NENIWDhSCwACAAAACVUxREZFQlhWMwsAAwAAAAtGMDZTUDdKNzJKSwAKAAQAAAAAAAlEGAALAAIAAAAUdaTPph-EUtwh2fKDBE3b9sgM8c8A?client_context_team_id=TXXXXXXXX ``` ``` OK - 607256 ``` ```http POST https://xxx.slack.com/api/files.completeUpload?_x_id=99be626d-1712389823.269&_x_csid=fgNfxlapd2M&slack_route=TXXXXXXXX&_x_version_ts=1712363845&_x_frontend_build_type=current&_x_desktop_ia=4&_x_gantry=true&fp=92 ``` ```json {"ok":true,"files":[{"id":"F06SP7J72JK","title":"2024-04-03_22h59_00.mp4"}]} ``` ```http POST https://xxx.slack.com/api/files.info?_x_id=99be626d-1712389825.506&_x_csid=fgNfxlapd2M&slack_route=TXXXXXXXX&_x_version_ts=1712363845&_x_frontend_build_type=current&_x_desktop_ia=4&_x_gantry=true&fp=92 ``` ```json { "ok": true, "file": { "id": "F06SP7J72JK", "created": 1712389821, "timestamp": 1712389821, "name": "2024-04-03_22h59_00.mp4", "title": "2024-04-03_22h59_00.mp4", "mimetype": "video\/mp4", "filetype": "mp4", "pretty_type": "MPEG 4 Video", "user": "U1DFEBXV3", "user_team": "TXXXXXXXX", "editable": false, "size": 607256, "mode": "hosted", "is_external": false, "external_type": "", "is_public": false, "public_url_shared": false, "display_as_bot": false, "username": "", "transcription": { "status": "processing" }, "mp4": "https:\/\/files.slack.com\/files-tmb\/TXXXXXXXX-F06SP7J72JK-7cdff2a2ef\/2024-04-03_22h59_00.mp4", "url_private": "https:\/\/files.slack.com\/files-tmb\/TXXXXXXXX-F06SP7J72JK-7cdff2a2ef\/2024-04-03_22h59_00.mp4", "url_private_download": "https:\/\/files.slack.com\/files-pri\/TXXXXXXXX-F06SP7J72JK\/download\/2024-04-03_22h59_00.mp4", "media_display_type": "video", "thumb_video": "https:\/\/files.slack.com\/files-tmb\/TXXXXXXXX-F06SP7J72JK-7cdff2a2ef\/2024-04-03_22h59_00_thumb_video.jpeg", "thumb_video_w": 996, "thumb_video_h": 880, "permalink": "https:\/\/xxx.slack.com\/files\/U1DFEBXV3\/F06SP7J72JK\/2024-04-03_22h59_00.mp4", "permalink_public": "https:\/\/slack-files.com\/TXXXXXXXX-F06SP7J72JK-c4ec8b2c72", "is_starred": false, "shares": {}, "channels": [], "groups": [], "ims": [], "has_more_shares": false, "has_rich_preview": false, "file_access": "visible", "comments_count": 0 }, "comments": [], "paging": { "count": 500, "total": 0, "page": 1, "pages": 0 } } ``` ### 投稿 ```http POST https://xxx.slack.com/api/files.share?_x_id=99be626d-1712390227.182&_x_csid=z8aeBUm8uB4&slack_route=TXXXXXXXX&_x_version_ts=1712363845&_x_frontend_build_type=current&_x_desktop_ia=4&_x_gantry=true&fp=92 draft_id: Dr06T3Q1GH7C files: F06SP7J72JK channel: C27UF296K broadcast: false client_msg_id: 8d16186c-3520-4998-9b2f-c92951573206 blocks: [{"type":"rich_text","elements":[{"type":"rich_text_section","elements":[{"type":"text","text":"hoge"}]}]}] resharing_aware: true skip_dlp_user_warning: false from_share_modal: false unfurl: [] client_context_team_id: TXXXXXXXX ``` ```json {"ok":true,"file_msg_ts":"1712390227.555439"} ``` ## channel未指定アップロードを試す ```http POST https://slack.com/api/files.upload // fileのみを指定 ``` ```json { "ok": true, "file": { "id": "F06TSM1RL4Q", "created": 1712395309, "timestamp": 1712395309, "name": "2024-04-06_18h20_50.mp4", "title": "2024-04-06 18h20 50", "mimetype": "video\/mp4", "filetype": "mp4", "pretty_type": "MPEG 4 Video", "user": "U1DFEBXV3", "user_team": "TXXXXXXXX", "editable": false, "size": 17109, "mode": "hosted", "is_external": false, "external_type": "", "is_public": false, "public_url_shared": false, "display_as_bot": false, "username": "", "url_private": "https:\/\/files.slack.com\/files-pri\/TXXXXXXXX-F06TSM1RL4Q\/2024-04-06_18h20_50.mp4", "url_private_download": "https:\/\/files.slack.com\/files-pri\/TXXXXXXXX-F06TSM1RL4Q\/download\/2024-04-06_18h20_50.mp4", "media_display_type": "video", "thumb_video": "https:\/\/files.slack.com\/files-tmb\/TXXXXXXXX-F06TSM1RL4Q-9dd1a81a68\/2024-04-06_18h20_50_thumb_video.jpeg", "thumb_video_w": 384, "thumb_video_h": 322, "permalink": "https:\/\/xxx.slack.com\/files\/U1DFEBXV3\/F06TSM1RL4Q\/2024-04-06_18h20_50.mp4", "permalink_public": "https:\/\/slack-files.com\/TXXXXXXXX-F06TSM1RL4Q-6c481581ff", "comments_count": 0, "is_starred": false, "shares": {}, "channels": [], "groups": [], "ims": [], "has_more_shares": false, "has_rich_preview": false, "file_access": "visible" } } ``` 以下のリクエストで投稿。 ```console curl 'https://slack.com/api/chat.postMessage' \ -H 'accept: */*' \ -H 'accept-language: ja,en-US;q=0.9,en;q=0.8' \ -H 'authorization: Bearer xoxp-xxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'content-type: application/json;charset=utf-8' \ -H 'cookie: xxxx -H 'origin: chrome-extension://cgclgomkfeiepcgolbdflhoddnenimbc' \ -H 'sec-ch-ua: "Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "Windows"' \ -H 'sec-fetch-dest: empty' \ -H 'sec-fetch-mode: cors' \ -H 'sec-fetch-site: none' \ -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36' \ --data-raw '{"channel":"C27UF296K","blocks":[{"type":"section","text":{"type":"mrkdwn","text":"test2"}},{"type":"file","external_id":"F06T3TYHFL2","source":"remote"},{"type":"divider"},{"type":"context","elements":[{"type":"image","image_url":"https://github.com/tadashi-aikawa/fenice/raw/master/public/icon/384.png","alt_text":"fenice"},{"type":"mrkdwn","text":"Posted via Fenice"}]}]}' ``` bot_userのエラー? ```error {"ok":false,"error":"no_bot_user"} ``` ## no_bot_userの謎に迫る 調べてる限りだと原因はイマイチ分からない。。[[ChatGPT Plus]]に聞いてみた感じだと別のアプローチをとったほうがよさそう。 ## permalinkを展開する 単に動画が共有できればいいのなら、permalinkを本文に貼り付けるのが一番楽。`mrkdwn`で空白文字に対してリンクを埋め込むことにより、文字は登場せずメディアを埋め込める。 ```json { "channel": "#test_tadashi-aikawa", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "てすと" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "<https://xxx.slack.com/files/U1DFEBXV3/F06TSM1RL4Q/2024-04-06_18h20_50.mp4| >" } } ] } ``` ## backup ```ts const videoBlocks: VideoBlock[] = files.value .filter((x) => x.type === "video") .map((x) => ({ type: "video", alt_text: "video", title: { type: "plain_text", text: "Pasted video", emoji: false, }, thumbnail_url: x.thumbnail!, video_url: x.url!, })); ```