mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
Feature/slack status change (#995)
* Added methods to set and get the user's status. * Fixed set status message * Improvements to #993 * 💄 small cosmetic change Co-authored-by: Tobias Schulz-Hess <tobias+xps@schulz-hess.de> Co-authored-by: Tobias Schulz-Hess <tobias.schulz-hess@xing.com>
This commit is contained in:
parent
fe802c8f76
commit
39c173a272
|
@ -10,6 +10,8 @@ const userScopes = [
|
||||||
'files:write',
|
'files:write',
|
||||||
'stars:read',
|
'stars:read',
|
||||||
'stars:write',
|
'stars:write',
|
||||||
|
'users.profile:read',
|
||||||
|
'users.profile:write'
|
||||||
];
|
];
|
||||||
|
|
||||||
export class SlackOAuth2Api implements ICredentialType {
|
export class SlackOAuth2Api implements ICredentialType {
|
||||||
|
|
|
@ -16,26 +16,37 @@ import {
|
||||||
channelFields,
|
channelFields,
|
||||||
channelOperations,
|
channelOperations,
|
||||||
} from './ChannelDescription';
|
} from './ChannelDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
messageFields,
|
messageFields,
|
||||||
messageOperations,
|
messageOperations,
|
||||||
} from './MessageDescription';
|
} from './MessageDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
starFields,
|
starFields,
|
||||||
starOperations,
|
starOperations,
|
||||||
} from './StarDescription';
|
} from './StarDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fileFields,
|
fileFields,
|
||||||
fileOperations,
|
fileOperations,
|
||||||
} from './FileDescription';
|
} from './FileDescription';
|
||||||
|
|
||||||
|
import {
|
||||||
|
userProfileFields,
|
||||||
|
userProfileOperations,
|
||||||
|
} from './UserProfileDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
slackApiRequest,
|
slackApiRequest,
|
||||||
slackApiRequestAllItems,
|
slackApiRequestAllItems,
|
||||||
validateJSON,
|
validateJSON,
|
||||||
} from './GenericFunctions';
|
} from './GenericFunctions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IAttachment,
|
IAttachment,
|
||||||
} from './MessageInterface';
|
} from './MessageInterface';
|
||||||
|
import moment = require('moment');
|
||||||
|
|
||||||
interface Attachment {
|
interface Attachment {
|
||||||
fields: {
|
fields: {
|
||||||
|
@ -156,6 +167,10 @@ export class Slack implements INodeType {
|
||||||
name: 'Star',
|
name: 'Star',
|
||||||
value: 'star',
|
value: 'star',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'User Profile',
|
||||||
|
value: 'userProfile',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
default: 'message',
|
default: 'message',
|
||||||
description: 'The resource to operate on.',
|
description: 'The resource to operate on.',
|
||||||
|
@ -169,6 +184,8 @@ export class Slack implements INodeType {
|
||||||
...starFields,
|
...starFields,
|
||||||
...fileOperations,
|
...fileOperations,
|
||||||
...fileFields,
|
...fileFields,
|
||||||
|
...userProfileOperations,
|
||||||
|
...userProfileFields,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,6 +235,22 @@ export class Slack implements INodeType {
|
||||||
|
|
||||||
return returnData;
|
return returnData;
|
||||||
},
|
},
|
||||||
|
// Get all the team fields to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getTeamFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
const { profile: { fields } } = await slackApiRequest.call(this, 'GET', '/team.profile.get');
|
||||||
|
console.log(fields);
|
||||||
|
for (const field of fields) {
|
||||||
|
const fieldName = field.label;
|
||||||
|
const fieldId = field.id;
|
||||||
|
returnData.push({
|
||||||
|
name: fieldName,
|
||||||
|
value: fieldId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return returnData;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -232,6 +265,7 @@ export class Slack implements INodeType {
|
||||||
const operation = this.getNodeParameter('operation', 0) as string;
|
const operation = this.getNodeParameter('operation', 0) as string;
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
|
responseData = { error: 'Resource ' + resource + ' / operation ' + operation + ' not found!'};
|
||||||
qs = {};
|
qs = {};
|
||||||
if (resource === 'channel') {
|
if (resource === 'channel') {
|
||||||
//https://api.slack.com/methods/conversations.archive
|
//https://api.slack.com/methods/conversations.archive
|
||||||
|
@ -848,6 +882,55 @@ export class Slack implements INodeType {
|
||||||
responseData = responseData.file;
|
responseData = responseData.file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (resource === 'userProfile') {
|
||||||
|
//https://api.slack.com/methods/users.profile.set
|
||||||
|
if (operation === 'update') {
|
||||||
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
|
||||||
|
const timezone = this.getTimezone();
|
||||||
|
|
||||||
|
const body: IDataObject = {};
|
||||||
|
|
||||||
|
Object.assign(body, additionalFields);
|
||||||
|
|
||||||
|
if (body.status_expiration === undefined) {
|
||||||
|
body.status_expiration = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
body.status_expiration = moment.tz(body.status_expiration as string, timezone).unix();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.customFieldUi) {
|
||||||
|
const customFields = (body.customFieldUi as IDataObject).customFieldValues as IDataObject[];
|
||||||
|
|
||||||
|
body.fields = {};
|
||||||
|
|
||||||
|
for (const customField of customFields) {
|
||||||
|
//@ts-ignore
|
||||||
|
body.fields[customField.id] = {
|
||||||
|
value: customField.value,
|
||||||
|
alt: customField.alt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData = await slackApiRequest.call(this, 'POST', '/users.profile.set', { profile: body }, qs);
|
||||||
|
|
||||||
|
responseData = responseData.profile;
|
||||||
|
}
|
||||||
|
//https://api.slack.com/methods/users.profile.get
|
||||||
|
if (operation === 'get') {
|
||||||
|
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
|
||||||
|
|
||||||
|
const body: IDataObject = {};
|
||||||
|
|
||||||
|
Object.assign(body, additionalFields);
|
||||||
|
|
||||||
|
responseData = await slackApiRequest.call(this, 'POST', '/users.profile.get', body);
|
||||||
|
|
||||||
|
responseData = responseData.profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Array.isArray(responseData)) {
|
if (Array.isArray(responseData)) {
|
||||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||||
} else {
|
} else {
|
||||||
|
|
183
packages/nodes-base/nodes/Slack/UserProfileDescription.ts
Normal file
183
packages/nodes-base/nodes/Slack/UserProfileDescription.ts
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
import {
|
||||||
|
INodeProperties,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
import { text } from 'express';
|
||||||
|
|
||||||
|
export const userProfileOperations = [
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'userProfile',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
description: `Get your user's profile`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Update',
|
||||||
|
value: 'update',
|
||||||
|
description: `Update user's profile`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'get',
|
||||||
|
description: 'The operation to perform.',
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
||||||
|
|
||||||
|
export const userProfileFields = [
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* userProfile:update */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'userProfile',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Custom Fields',
|
||||||
|
name: 'customFieldUi',
|
||||||
|
placeholder: 'Add Custom Fields',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
typeOptions: {
|
||||||
|
multipleValues: true,
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'customFieldValues',
|
||||||
|
displayName: 'Custom Field',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Field ID',
|
||||||
|
name: 'id',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getTeamFields',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
description: 'ID of the field to set.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Field Value',
|
||||||
|
name: 'value',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'Value of the field to set.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Alt',
|
||||||
|
name: 'alt',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Email',
|
||||||
|
name: 'email',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: `This field can only be changed by admins for users on paid teams.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'First Name',
|
||||||
|
name: 'first_name',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Last Name',
|
||||||
|
name: 'last_name',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Status Emoji',
|
||||||
|
name: 'status_emoji',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: `is a string referencing an emoji enabled for the Slack team, such as :mountain_railway:`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Status Expiration',
|
||||||
|
name: 'status_expiration',
|
||||||
|
type: 'dateTime',
|
||||||
|
default: '',
|
||||||
|
description: `is an integer specifying seconds since the epoch, more commonly known as "UNIX time". Providing 0 or omitting this field results in a custom status that will not expire`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Status Text',
|
||||||
|
name: 'status_text',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: `allows up to 100 characters, though we strongly encourage brevity.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'User ID',
|
||||||
|
name: 'user',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: `ID of user to change. This argument may only be specified by team admins on paid teams.`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* userProfile:get */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
default: {},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: [
|
||||||
|
'userProfile',
|
||||||
|
],
|
||||||
|
operation: [
|
||||||
|
'get',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Include Labels',
|
||||||
|
name: 'include_labels',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
description: `Include labels for each ID in custom profile fields`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'User ID',
|
||||||
|
name: 'user',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: `User to retrieve profile info for`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as INodeProperties[];
|
Loading…
Reference in a new issue