Skip to content
This repository has been archived by the owner on Nov 6, 2023. It is now read-only.

Feat/telegram integration #220

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions packages/api-plugin-template.erxes/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ app.disable('x-powered-by');

app.use(cors());

//@ts-ignore
app.use(cookieParser());

// for health checking
Expand Down
14 changes: 14 additions & 0 deletions packages/plugin-telegram-api/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# general
NODE_ENV=development
PORT=4011

# MongoDB
MONGO_URL=mongodb://localhost/erxes

# RabbitMQ
RABBITMQ_HOST=amqp://localhost

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
13 changes: 13 additions & 0 deletions packages/plugin-telegram-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@erxes/plugin-telegram-api",
"version": "1.0.0",
"scripts": {
"install-deps": "cd .erxes && yarn install",
"dev": "cd .erxes && yarn dev",
"build": "cd .erxes && yarn build",
"start": "cd .erxes/dist/plugin-telegram-api/.erxes && node src"
},
"dependencies": {
"telegraf": "^4.12.2"
}
}
72 changes: 72 additions & 0 deletions packages/plugin-telegram-api/src/bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Telegraf } from 'telegraf';
import { receiveMessage } from './receiveMessage';
import { message } from 'telegraf/filters';
import { Chats } from './models';

export class TelegramBot {
private _bot;
private _info;
error?: string;

constructor(botToken: string) {
try {
this._bot = new Telegraf(botToken);
} catch (e) {
this.error = e.message;
}
}

getMe = async () => {
const me = await this._bot.telegram.getMe();
this._info = me;
return me;
};

run = async accountId => {
if (!this._info) {
await this.getMe();
}
this._bot.on(message('text'), receiveMessage(accountId));

this._bot.on(['my_chat_member'], async ctx => {
await this.updateChat(ctx, accountId);
});

this._bot.launch();
console.log(`Bot "${this._info.username}" is running`);
return;
};

updateChat = async (ctx, botAccountId) => {
const update = ctx.update;
const memberUpdate = update.my_chat_member;
const { chat, new_chat_member } = memberUpdate;
const { id: telegramId, title, type: chatType } = chat;

switch (new_chat_member.status) {
case 'kicked':
case 'left':
console.log(`Removing telegram chat: ${telegramId}`);
const removingResult = await Chats.remove({
botAccountId,
telegramId
});
return;
case 'member':
case 'administrator':
console.log(`Add/Updating telegram chat: ${telegramId}`);
const addingChat = await Chats.createOrUpdate(
{ telegramId, botAccountId },
{
botAccountId,
telegramId,
title,
chatType,
memberType: new_chat_member.status
}
);
default:
return;
}
};
}
43 changes: 43 additions & 0 deletions packages/plugin-telegram-api/src/configs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import typeDefs from './graphql/typeDefs';
import resolvers from './graphql/resolvers';

import { initBroker } from './messageBroker';
import init from './controller';

export let mainDb;
export let graphqlPubsub;
export let serviceDiscovery;

export let debug;

export default {
name: 'telegram',
graphql: sd => {
serviceDiscovery = sd;
return {
typeDefs,
resolvers
};
},
meta: {
inboxIntegration: {
kind: 'telegram',
label: 'Telegram'
}
},
apolloServerContext: async context => {
return context;
},

onServerInit: async options => {
const app = options.app;
mainDb = options.db;

debug = options.debug;
graphqlPubsub = options.pubsubClient;

initBroker(options.messageBrokerClient);

init(app);
}
};
38 changes: 38 additions & 0 deletions packages/plugin-telegram-api/src/controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Accounts, Chats } from './models';
import { TelegramBot } from './bot';

const searchMessages = (linkedin, criteria) => {
return new Promise((resolve, reject) => {
const messages: any = [];
});
};

// controller for telegram
const init = async app => {
const accounts = await Accounts.find({});

accounts.forEach(acct => {
const bot = new TelegramBot(acct.token);
bot.run(acct.id);
});
// TODO: read accounts from mongo and spawn a bot for each account

app.get('/chats', async (req, res) => {
const chats = await Chats.find({});
res.send(chats);
});

app.post('/receive', async (req, res, next) => {
try {
// write receive code here

res.send('Successfully receiving message');
} catch (e) {
return next(new Error(e));
}

res.sendStatus(200);
});
};

export default init;
9 changes: 9 additions & 0 deletions packages/plugin-telegram-api/src/graphql/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import resolvers from './resolvers';
import typeDefs from './typeDefs';

const mod = {
resolvers,
typeDefs
};

export default mod;
15 changes: 15 additions & 0 deletions packages/plugin-telegram-api/src/graphql/resolvers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import customScalars from '@erxes/api-utils/src/customScalars';
import mutations from './mutations';
import queries from './queries';

const resolvers: any = {
...customScalars,
Mutation: {
...mutations
},
Query: {
...queries
}
};

export default resolvers;
36 changes: 36 additions & 0 deletions packages/plugin-telegram-api/src/graphql/resolvers/mutations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { TelegramBot } from '../../bot';
import { Accounts, Chats } from '../../models';
import { IContext } from '@erxes/api-utils/src/types';

const telegramMutations = {
async telegramAccountRemove(
_root,
{ _id }: { _id: string },
_context: IContext
) {
await Accounts.removeAccount(_id);

return 'deleted';
},

async telegramAccountAdd(_root, { token }, _context: IContext) {
const currentAccount = await Accounts.findOne({ token });

if (!currentAccount) {
const bot = new TelegramBot(token);
const info = await bot.getMe();
const account = await Accounts.create({
token,
name: info.username
});

bot.run(account.id);

return 'Account created';
}

throw new Error(`Account already exists: ${currentAccount.name}`);
}
};

export default telegramMutations;
42 changes: 42 additions & 0 deletions packages/plugin-telegram-api/src/graphql/resolvers/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { IContext } from '@erxes/api-utils/src/types';
import { Accounts, Chats, Messages } from '../../models';

const queries = {
async telegramConversationDetail(
_root,
{ conversationId },
_context: IContext
) {
const messages = await Messages.find({
inboxConversationId: conversationId
});

const convertEmails = emails =>
(emails || []).map(item => ({ name: item.name, email: item.address }));

return messages.map(message => {
return {
_id: message._id,
mailData: {
messageId: message.messageId,
from: convertEmails(message.from),
to: convertEmails(message.to),
cc: convertEmails(message.cc),
bcc: convertEmails(message.bcc),
subject: message.subject,
body: message.body
}
};
});
},

async telegramAccounts(_root, _args, _context: IContext) {
return Accounts.getAccounts();
},

async telegramChats(_root, _args, _context: IContext) {
return Chats.getAllChats();
}
};

export default queries;
37 changes: 37 additions & 0 deletions packages/plugin-telegram-api/src/graphql/typeDefs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { gql } from 'apollo-server-express';

const types = `
type Telegram {
_id: String!
title: String
mailData: JSON
}
`;

const queries = `
telegramConversationDetail(conversationId: String!): [Telegram]
telegramAccounts: JSON
telegramChats: JSON
`;

const mutations = `
telegramAccountRemove(_id: String!): String
telegramAccountAdd(token: String!): String
`;

const typeDefs = gql`
scalar JSON
scalar Date

${types}

extend type Query {
${queries}
}

extend type Mutation {
${mutations}
}
`;

export default typeDefs;
Loading