Add support to send files in Slack CLI tool (#39778)
* Add a file upload command to the slack CLI. * Clean up, add file command to program. * Rename the command to 'file' * Better error handling, don't ask for file info.
This commit is contained in:
parent
2afba8b8fe
commit
3e9656187a
|
@ -3592,6 +3592,9 @@ importers:
|
|||
'@octokit/types':
|
||||
specifier: ^9.2.0
|
||||
version: 9.2.0
|
||||
'@slack/web-api':
|
||||
specifier: ^6.9.0
|
||||
version: 6.9.0
|
||||
'@types/cli-table':
|
||||
specifier: ^0.3.1
|
||||
version: 0.3.1
|
||||
|
@ -12433,8 +12436,8 @@ packages:
|
|||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dependencies:
|
||||
'@babel/core': 7.21.3
|
||||
'@jest/types': 29.5.0
|
||||
'@jridgewell/trace-mapping': 0.3.17
|
||||
'@jest/types': 29.6.1
|
||||
'@jridgewell/trace-mapping': 0.3.19
|
||||
babel-plugin-istanbul: 6.1.1
|
||||
chalk: 4.1.2
|
||||
convert-source-map: 2.0.0
|
||||
|
@ -12442,7 +12445,7 @@ packages:
|
|||
graceful-fs: 4.2.9
|
||||
jest-haste-map: 29.5.0
|
||||
jest-regex-util: 29.4.3
|
||||
jest-util: 29.5.0
|
||||
jest-util: 29.6.2
|
||||
micromatch: 4.0.5
|
||||
pirates: 4.0.5
|
||||
slash: 3.0.0
|
||||
|
@ -13917,6 +13920,11 @@ packages:
|
|||
engines: {node: '>= 12.13.0', npm: '>= 6.12.0'}
|
||||
dev: false
|
||||
|
||||
/@slack/types@2.8.0:
|
||||
resolution: {integrity: sha512-ghdfZSF0b4NC9ckBA8QnQgC9DJw2ZceDq0BIjjRSv6XAZBXJdWgxIsYz0TYnWSiqsKZGH2ZXbj9jYABZdH3OSQ==}
|
||||
engines: {node: '>= 12.13.0', npm: '>= 6.12.0'}
|
||||
dev: false
|
||||
|
||||
/@slack/web-api@5.15.0:
|
||||
resolution: {integrity: sha512-tjQ8Zqv/Fmj9SOL9yIEd7IpTiKfKHi9DKAkfRVeotoX0clMr3SqQtBqO+KZMX27gm7dmgJsQaDKlILyzdCO+IA==}
|
||||
engines: {node: '>= 8.9.0', npm: '>= 5.5.1'}
|
||||
|
@ -13954,6 +13962,25 @@ packages:
|
|||
- debug
|
||||
dev: false
|
||||
|
||||
/@slack/web-api@6.9.0:
|
||||
resolution: {integrity: sha512-RME5/F+jvQmZHkoP+ogrDbixq1Ms1mBmylzuWq4sf3f7GCpMPWoiZ+WqWk+sism3vrlveKWIgO9R4Qg9fiRyoQ==}
|
||||
engines: {node: '>= 12.13.0', npm: '>= 6.12.0'}
|
||||
dependencies:
|
||||
'@slack/logger': 3.0.0
|
||||
'@slack/types': 2.8.0
|
||||
'@types/is-stream': 1.1.0
|
||||
'@types/node': 16.18.21
|
||||
axios: 0.27.2
|
||||
eventemitter3: 3.1.2
|
||||
form-data: 2.5.1
|
||||
is-electron: 2.2.2
|
||||
is-stream: 1.1.0
|
||||
p-queue: 6.6.2
|
||||
p-retry: 4.6.1
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/@storybook/addon-a11y@6.5.17-alpha.0(react-dom@17.0.2)(react@17.0.2):
|
||||
resolution: {integrity: sha512-ZjYxGpuN7/euPscmgQys6QJ+ASVxrFHh28HPd8SqH+j1UmTiGnwPFYmUTm8sY8fMwormdy/H/phQ8FX6xNZ31Q==}
|
||||
peerDependencies:
|
||||
|
@ -21510,6 +21537,15 @@ packages:
|
|||
- debug
|
||||
dev: true
|
||||
|
||||
/axios@0.27.2:
|
||||
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
|
||||
dependencies:
|
||||
follow-redirects: 1.15.2(debug@4.3.3)
|
||||
form-data: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/axobject-query@2.2.0:
|
||||
resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==}
|
||||
|
||||
|
@ -30405,6 +30441,10 @@ packages:
|
|||
resolution: {integrity: sha512-SpMppC2XR3YdxSzczXReBjqs2zGscWQpBIKqwXYBFic0ERaxNVgwLCHwOLZeESfdJQjX0RDvrJ1lBXX2ij+G1Q==}
|
||||
dev: false
|
||||
|
||||
/is-electron@2.2.2:
|
||||
resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==}
|
||||
dev: false
|
||||
|
||||
/is-extendable@0.1.1:
|
||||
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -37963,7 +38003,7 @@ packages:
|
|||
postcss: 8.4.21
|
||||
schema-utils: 3.1.1
|
||||
semver: 7.5.0
|
||||
webpack: 5.70.0(webpack-cli@4.9.2)
|
||||
webpack: 5.70.0(webpack-cli@3.3.12)
|
||||
|
||||
/postcss-loader@4.3.0(postcss@8.4.21)(webpack@5.76.3):
|
||||
resolution: {integrity: sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==}
|
||||
|
@ -41117,7 +41157,7 @@ packages:
|
|||
sass: 1.60.0
|
||||
schema-utils: 3.1.1
|
||||
semver: 7.5.0
|
||||
webpack: 5.76.3(webpack-cli@3.3.12)
|
||||
webpack: 5.76.3(webpack-cli@4.9.2)
|
||||
dev: true
|
||||
|
||||
/sass-loader@12.6.0(sass@1.60.0)(webpack@5.76.3):
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
"promptly": "^3.2.0",
|
||||
"semver": "^7.3.2",
|
||||
"simple-git": "^3.10.0",
|
||||
"uuid": "^9.0.0"
|
||||
"uuid": "^9.0.0",
|
||||
"@slack/web-api": "^6.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.4.1",
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Command } from '@commander-js/extra-typings';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { slackMessageCommand } from './slack-message';
|
||||
import { slackFileCommand } from './slack-file';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -14,6 +15,7 @@ import { slackMessageCommand } from './slack-message';
|
|||
|
||||
const program = new Command( 'slack' )
|
||||
.description( 'Slack message sending utilities' )
|
||||
.addCommand( slackMessageCommand, { isDefault: true } );
|
||||
.addCommand( slackMessageCommand, { isDefault: true } )
|
||||
.addCommand( slackFileCommand );
|
||||
|
||||
export default program;
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Command } from '@commander-js/extra-typings';
|
||||
import { ErrorCode, WebClient } from '@slack/web-api';
|
||||
import { basename } from 'path';
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { existsSync } from 'fs';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Logger } from '../../../core/logger';
|
||||
|
||||
export const slackFileCommand = new Command( 'file' )
|
||||
.description( 'Send a file upload message to a slack channel' )
|
||||
.argument(
|
||||
'<token>',
|
||||
'Slack authentication token bearing required scopes.'
|
||||
)
|
||||
.argument( '<text>', 'Text based message to send to the slack channel.' )
|
||||
.argument( '<filePath>', 'File path to upload to the slack channel.' )
|
||||
.argument(
|
||||
'<channelIds...>',
|
||||
'Slack channel IDs to send the message to. Pass as many as you like.'
|
||||
)
|
||||
.option(
|
||||
'--dont-fail',
|
||||
'Do not fail the command if a message fails to send to any channel.'
|
||||
)
|
||||
.action( async ( token, text, filePath, channels, { dontFail } ) => {
|
||||
Logger.startTask(
|
||||
`Attempting to send message to Slack for channels: ${ channels.join(
|
||||
','
|
||||
) }`
|
||||
);
|
||||
|
||||
const shouldFail = ! dontFail;
|
||||
|
||||
if ( filePath && ! existsSync( filePath ) ) {
|
||||
Logger.error(
|
||||
`Unable to open file with path: ${ filePath }`,
|
||||
shouldFail
|
||||
);
|
||||
}
|
||||
|
||||
const client = new WebClient( token );
|
||||
|
||||
for ( const channel of channels ) {
|
||||
try {
|
||||
await client.files.uploadV2( {
|
||||
file: filePath,
|
||||
filename: basename( filePath ),
|
||||
channel_id: channel,
|
||||
initial_comment: text.replace( /\\n/g, '\n' ),
|
||||
request_file_info: false,
|
||||
} );
|
||||
|
||||
Logger.notice(
|
||||
`Successfully uploaded ${ filePath } to channel: ${ channel }`
|
||||
);
|
||||
} catch ( e ) {
|
||||
if (
|
||||
'code' in e &&
|
||||
e.code === ErrorCode.PlatformError &&
|
||||
'message' in e &&
|
||||
e.message.includes( 'missing_scope' )
|
||||
) {
|
||||
Logger.error(
|
||||
`The provided token does not have the required scopes, please add files:write and chat:write to the token.`,
|
||||
shouldFail
|
||||
);
|
||||
} else {
|
||||
Logger.error( e, shouldFail );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.endTask();
|
||||
} );
|
Loading…
Reference in New Issue