Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add chat messages to MS Teams node #2635

Merged
merged 3 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class MicrosoftTeamsOAuth2Api implements ICredentialType {
displayName: 'Scope',
name: 'scope',
type: 'hidden',
default: 'openid offline_access User.ReadWrite.All Group.ReadWrite.All',
default: 'openid offline_access User.ReadWrite.All Group.ReadWrite.All Chat.ReadWrite',
},
];
}
201 changes: 201 additions & 0 deletions packages/nodes-base/nodes/Microsoft/Teams/ChatMessageDescription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import {
INodeProperties,
} from 'n8n-workflow';

export const chatMessageOperations: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'chatMessage',
],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create a message',
},
{
name: 'Get',
value: 'get',
description: 'Get a message',
},
{
name: 'Get All',
value: 'getAll',
description: 'Get all messages',
},
],
default: 'create',
description: 'The operation to perform.',
},
];

export const chatMessageFields: INodeProperties[] = [

/* -------------------------------------------------------------------------- */
/* chatMessage:create */
/* -------------------------------------------------------------------------- */
{
displayName: 'Chat ID',
name: 'chatId',
required: true,
type: 'options',
typeOptions: {
loadOptionsMethod: 'getChats',
},
displayOptions: {
show: {
operation: [
'create',
'get',
],
resource: [
'chatMessage',
],
},
},
default: '',
description: 'Chat ID',
},
{
displayName: 'Message Type',
name: 'messageType',
required: true,
type: 'options',
options: [
{
name: 'Text',
value: 'text',
},
{
name: 'HTML',
value: 'html',
},
],
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'chatMessage',
],
},
},
default: '',
description: 'The type of the content',
},
{
displayName: 'Message',
name: 'message',
required: true,
type: 'string',
typeOptions: {
alwaysOpenEditWindow: true,
},
displayOptions: {
show: {
operation: [
'create',
],
resource: [
'chatMessage',
],
},
},
default: '',
description: 'The content of the item.',
},

/* -------------------------------------------------------------------------- */
/* chatMessage:get */
/* -------------------------------------------------------------------------- */
{
displayName: 'Message ID',
name: 'messageId',
required: true,
type: 'string',
displayOptions: {
show: {
operation: [
'get',
],
resource: [
'chatMessage',
],
},
},
default: '',
},
/* -------------------------------------------------------------------------- */
/* chatMessage:getAll */
/* -------------------------------------------------------------------------- */
{
displayName: 'Chat ID',
name: 'chatId',
required: true,
type: 'options',
typeOptions: {
loadOptionsMethod: 'getChats',
},
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'chatMessage',
],
},
},
default: '',
description: 'Chat ID',
},
{
displayName: 'Return All',
name: 'returnAll',
type: 'boolean',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'chatMessage',
],
},
},
default: false,
description: 'If all results should be returned or only up to a given limit.',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
displayOptions: {
show: {
operation: [
'getAll',
],
resource: [
'chatMessage',
],
returnAll: [
false,
],
},
},
typeOptions: {
minValue: 1,
maxValue: 500,
},
default: 100,
description: 'How many results to return.',
},
];
67 changes: 67 additions & 0 deletions packages/nodes-base/nodes/Microsoft/Teams/MicrosoftTeams.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ import {
channelMessageOperations,
} from './ChannelMessageDescription';

import {
chatMessageFields,
chatMessageOperations,
} from './ChatMessageDescription';

import {
taskFields,
taskOperations,
Expand Down Expand Up @@ -65,6 +70,10 @@ export class MicrosoftTeams implements INodeType {
name: 'Channel Message (Beta)',
value: 'channelMessage',
},
{
name: 'Chat Message',
value: 'chatMessage',
},
{
name: 'Task',
value: 'task',
Expand All @@ -79,6 +88,8 @@ export class MicrosoftTeams implements INodeType {
/// MESSAGE
...channelMessageOperations,
...channelMessageFields,
...chatMessageOperations,
...chatMessageFields,
///TASK
...taskOperations,
...taskFields,
Expand Down Expand Up @@ -189,6 +200,29 @@ export class MicrosoftTeams implements INodeType {
}
return returnData;
},
// Get all the chats to display them to user so that they can
// select them easily
async getChats(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const qs: IDataObject = {
$expand: 'members',
};
const { value } = await microsoftApiRequest.call(this, 'GET', '/v1.0/chats', {}, qs);
for (const chat of value) {
if (!chat.topic) {
chat.topic = chat.members
.filter((member: IDataObject) => member.displayName)
.map((member: IDataObject) => member.displayName).join(', ');
}
const chatName = `${chat.topic || '(no title) - ' + chat.id} (${chat.chatType})`;
const chatId = chat.id;
returnData.push({
name: chatName,
value: chatId,
});
}
return returnData;
},
},
};

Expand Down Expand Up @@ -298,6 +332,39 @@ export class MicrosoftTeams implements INodeType {
}
}
}
if (resource === 'chatMessage') {
// https://docs.microsoft.com/en-us/graph/api/channel-post-messages?view=graph-rest-1.0&tabs=http
if (operation === 'create') {
const chatId = this.getNodeParameter('chatId', i) as string;
const messageType = this.getNodeParameter('messageType', i) as string;
const message = this.getNodeParameter('message', i) as string;
const body: IDataObject = {
body: {
contentType: messageType,
content: message,
},
};
responseData = await microsoftApiRequest.call(this, 'POST', `/v1.0/chats/${chatId}/messages`, body);
}
// https://docs.microsoft.com/en-us/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http
if (operation === 'get') {
const chatId = this.getNodeParameter('chatId', i) as string;
const messageId = this.getNodeParameter('messageId', i) as string;
responseData = await microsoftApiRequest.call(this, 'GET', `/v1.0/chats/${chatId}/messages/${messageId}`);
}
// https://docs.microsoft.com/en-us/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http
if (operation === 'getAll') {
const chatId = this.getNodeParameter('chatId', i) as string;
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
if (returnAll) {
responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/v1.0/chats/${chatId}/messages`);
} else {
qs.limit = this.getNodeParameter('limit', i) as number;
responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/v1.0/chats/${chatId}/messages`, {});
responseData = responseData.splice(0, qs.limit);
}
}
}
if (resource === 'task') {
//https://docs.microsoft.com/en-us/graph/api/planner-post-tasks?view=graph-rest-1.0&tabs=http
if (operation === 'create') {
Expand Down