* Completes the file upload process by associating files with a channel
( uploadedFileIds: string[], channel: string, text: string, accessToken: string, threadTs?: string | null, blocks?: unknown[] | null )
| 148 | * Completes the file upload process by associating files with a channel |
| 149 | */ |
| 150 | async function completeSlackFileUpload( |
| 151 | uploadedFileIds: string[], |
| 152 | channel: string, |
| 153 | text: string, |
| 154 | accessToken: string, |
| 155 | threadTs?: string | null, |
| 156 | blocks?: unknown[] | null |
| 157 | ): Promise<{ ok: boolean; files?: any[]; error?: string }> { |
| 158 | const response = await fetch('https://slack.com/api/files.completeUploadExternal', { |
| 159 | method: 'POST', |
| 160 | headers: { |
| 161 | 'Content-Type': 'application/json', |
| 162 | Authorization: `Bearer ${accessToken}`, |
| 163 | }, |
| 164 | body: JSON.stringify({ |
| 165 | files: uploadedFileIds.map((id) => ({ id })), |
| 166 | channel_id: channel, |
| 167 | // Per Slack docs for files.completeUploadExternal: if `initial_comment` |
| 168 | // is provided, `blocks` is silently ignored. So when blocks are present |
| 169 | // we omit initial_comment and let blocks render instead. |
| 170 | ...(blocks && blocks.length > 0 ? { blocks } : { initial_comment: text }), |
| 171 | ...(threadTs && { thread_ts: threadTs }), |
| 172 | }), |
| 173 | }) |
| 174 | |
| 175 | return response.json() |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Creates a message object for file uploads |