THIS PACKAGE HAS MOVED
Please see the latest official package here, thank you!
Zoom-bot-sdk
This library provide interfaces to quickly build bots and applications for Zoom Messaging framework. All the complexities of oAuth2, sending messages and receiving notifications to and from Zoom client are hidden within the library so that you can focus on building the business logic of your application.
Requirements
This package supports Node v8 and higher.
Installation
npm install zoom-bot-sdk
Features
Zoom connector offers Resource Owner && Authorization Server for you to integrate with zoom client . Each app can connect different user to trigger different actions(You need to install zoom client 4.4 or up to use the actions function in the bot)
Preparatory work
for developer,in marketplace
- click develop > build app > write app name&&select chat bot >create to create your new app
- add oauth url in marketplace App Credentials > redirect url for oauth ,just like https://domain/oauth2
- add webhook in marketplace feature > chat subscription > add command && add bot endpoint url,just like https://domain/webhook
- zoom openapi site
Example
oauth2 && webhook
const { oauth2, client, setting,log } = require('zoom-bot-sdk');
const db = require('./db');
let oauth2Client = oauth2(
process.env.zoomClientId,
process.env.zoomClientSecret,
process.env.zoomRedirect_uri+'/auth'
);
let zoomBot = client(
process.env.zoomClientId,
process.env.zoomVerifyCode,
process.env.zoomBotJid,
process.env.app
)
.commands([
{ command: 'meeting', description: 'request a meeting', hint: '<meetingno>' },
{ command: 'config', description: 'get config url', hint: '' }
])
.configurate({help:true,errorHelp:true})
.defaultAuth(oauth2Client.connect());
app.post('/auth',
async function(req,res,next){
let {code}=req.query;
try{
let connection=await oauth2Client.connectByCode(code);
let zoomApp=zoomBot.create({auth:connection});
res.locals.zoomApp=zoomApp;
next();
}
catch(e){
}
},
async function(req,res){
let { zoomApp } = res.locals;
let tokens = zoomApp.auth.getTokens();
try{
await db.models.zoom.save({access_token:tokens.access_tokens,....});
res.redirect('page url');
}
catch(e){
}
});
app.post('/webhook',
async function(req,res,next){
let {body,headers}=req;
try{
let wehookData = await zoomBot.handle({ body, headers });
let zoomApp = zoomBot.create({ auth: oauth2Client.connect() });
res.locals.zoomApp = zoomApp;
res.locals.wehookData = wehookData;
next();
}
catch(e){
}
},
async function(req,res){
let {zoomApp, wehookData}=res.locals;
let { payload,data,type,command,message } = wehookData;
let { toJid: to_jid,command,data, userId, accountId: account_id, channelName,name } = payload;
try{
await zoomApp.sendMessage({
to_jid,account_id,body,header
});
}
catch(e){
}
res.send();
})
app.post('/meeting',
async function(req,res,next){
let zoomApp = zoomBot.create({ auth: oauth2Client.connect() });
res.locals.zoomApp = zoomApp;
next();
},
async function(req,res){
let {zoomApp}=res.locals;
let item=db.models.zoom.get({id:...});
zoomApp.auth.setTokens({
access_token:item.get('access_token'),
refresh_token:item.get('refresh_token'),
expires_in:item.get('expires_in')
});
zoomApp.auth.callbackRefreshTokens(async function(tokens){
try{ await db.models.zoom.save({id,access_token:tokens.access_token,.....});}
catch(e){}
});
try{
await zoomApp.request({
url:'/v2/users/userid/meetings',
method:'post',
body:{...}
});
}
catch(e){
}
res.send();
});
sometimes,request maybe error,can retry via some condition,support request,getUser,sendMessage api to retry.
setting.retry({
sendMessage:{
no:3,
timeout(no,lg){return Math.random() * (10000 - 5000) + 5000;},
condition(backMsg,ind){
if(typeof backMsg==='object'&&backMsg.code&&backMsg.code.toString()==='7010'){
return true;
}
}
});
if you want all command case no sensitive
setting.caseSensitive(false);
if you want to debug your app
setting.debug(true);
DEBUG=http node index.js //now we only support http debug
what is connection
connection is a auth instance , we can create connection by oauth2Client.connectByCode(code) , oauth2Client.connectByRefresh(refreshcode) , oauth2Client.connectByTokens(tokens) tokens is from your db store , oauth2Client.connect() if you only need sendmessage to zoom im and you have know the relevant account_id and to_jid (these two datas you can get from webhook event payload or getUser)
after you create connection,you need bind it with your client instance ,just like let app=zoomBot.create({auth: oauth2Client.connect()}),the app instance which you can trigger the action
each user can create different connection,you can store some connections by own business demand
what is zoomBot
you can use zoomBot to configurate your commands,create account app, check command, parse webhook data and so on
zoomBot instance represents an bot on the marketplace , and after you use let app=zoomBot.create({auth: oauth2Client.connect()}) , you get a account instance which name app , you can use the account app to do the action ,just like get account id, sub user id , channel id in your current account , each app represents a new account.you can store you account app by own business demand
this lib integrate help command
after you bind webhook , then you write help in zoom im, and lib will auto send default content(which you configure in commands([])) to im
and if you send message in im which is not config in commands,you can use zoomBot.configurate({errorHelp:true}) and will send help content after write the command which in commands config.
Usage
global
const { oauth2, client, setting } = require('zoom-bot-sdk');
oauth2 with zoom
init oauth instance
const oauth2Client=oauth2(Your Client Id,Your Client Secret,Your redirect url);
oauth2Client.callbackNewTokens(function(tokens){
});
oauth2Client.callbackRefreshTokens(function(tokens){
});
oauth2Client.on('tokens',(tokens)=>{
});
oauth2Client.on('error',(err)=>{
});
create auth connection
let connection = await oauth2Client.connectByCode(code);
let connection = await oauth2Client.connectByRefresh(refresh_token);
let connection = oauth2Client.connectByTokens(tokens);
let connection = oauth2Client.connect();
connection api
let tokens = await connection.requestTokensByRefresh(refresh_token);
let tokens = await connection.requestTokens(code);
let clientTokens = await connection.requestClientTokens();
let ifExpired = connection.expired();
let ifClientExpired = connection.expiredClient();
let tokens = connection.getTokens();
let clientTokens = connection.getClientTokens();
connection.setTokens(tokens);
zoom client action && message
create zoombot instance and config command&&version for help command
let zoomBot=client(your clientid,your Verification Token,your robot_jid)
.command(opts).defaultAuth(oauth2Client.connect());
zoomBot= zoomBot.configurate({help:true,errorHelp:true});
let ifInCommands=zoombot.checkCommands(commandString);
if(!ifInCommands){await zoombot.triggerHelp(account_id,to_jid);}
create one business instance with oauth2 connection in zoombot
const userApp = zoomBot.create({
auth: connection
});
use business instance to handle action(for now,only support getUser,sendMessage three action,and you can also use request to request any api which not need to inject token auth)
use request to request any zoom open api
await userApp.request(opt, type);
get user
let userInfo = await userApp.getUser(email);
sendMessage
let backInfo = await userApp.sendMessage(option);
message event
handle request and get webhookData
expressApp.get('/someapi', async function(req, res, next) {
let { body, headers } = req;
try{
let webhookData=await zoomBot.handle({ body, headers });
}
catch(e){
console.log(e);
}
res.send('some res');
});
listen message model
zoomBot.on('actions', function(event) {
});
zoomBot.on('commands', function(event) {
});
action info format
button info
info:{
original:{"head":{"text":"reply from userName dev-lambda-bot-deploy"},"body":[{"type":"section","footer_icon":"https://platform.slack-edge.com/img/default_application_icon.png","footer":"some footer","sidebar_color":"#222222","sections":[{"type":"message","text":"section1"},{"type":"actions","limit":2,"items":[{"text":"button8888","style":"Danger","value":"button2"},{"text":"button3888","style":"Disabled","value":"button3"}]}]}]},
current:{"text":"button8888","value":"button2"}
}
dropdown info
info:{
original:{"head":{"text":"reply from userName dev-lambda-bot-deploy"},"body":[{"type":"select","text":"My Dropdown","style":{"color":"#987654","bold":false,"itatic":true},"selected_item":{"text":"t3","value":"v3"},"select_items":[{"text":"t1","value":"v1"},{"text":"t2","value":"v2"},{"text":"t3","value":"v3"},{"text":"t4","value":"v4"}]}]},
current:[{"value":"v4"}]
}
edit info
info:{
original:{"head":{"text":"reply from userName dev-lambda-bot-deploy"},"body":[{"type":"message","editable":true,"text":"sunday","style":{"color":"#000000"}}]},
current:{"origin":"sunday","target":"what's your name"}
}
body type
We will support more message body after the new zoom client release
{
"type":"message",
"text":"this is first message.",
"style":{
"color":"#FFFFFF",
"bold":true,
"itatic":false
}
}
{
"type":"message",
"text":"zoom.us",
"link":"https://zoom.us"
}
{
"type": "section",
"footer_icon": "https://platform.slack-edge.com/img/default_application_icon.png",
"footer": "some footer",
"sidebar_color": "#222222",
"sections": [
{
"type": "message",
"text": "section1"
},
{
"type": "actions",
"limit": 3,
"items": [
{
"text": "button8888",
"style": "Danger",
"value": "button2"
},
{
"text": "button3888",
"style": "Disabled",
"value": "button3"
},
{
"text": "button488",
"value": "button4"
}
]
}
]
}
{
"type": "fields",
"items": [
{
"key": "name",
"value": "lee yang",
"isName": true,
"short": true
},
{
"key": "zoom",
"value": "zoom.us",
"link": "https://zoom/us",
"short": true
}
]
}
{
"type": "attachments",
"resource_url": "https://docs.google.com/document/d/test/edit?usp=drive_web",
"img_url": "https://avatars1.githubusercontent.com/u/7495313?v=4",
"size": 3000,
"information": {
"title": {
"text": "test csv"
}
}
}
{
"type":"message",
"editable": true,
"text":"sunday",
"style":{
"color":"#000000"
}
}
{"text":"your header text"}
or
{"text":"your header text",
"style":{
"color":"#000000",
"bold":true,
"itatic":false
}
}
{"text":"your header text",
"sub_head":{
"text":"String",
"style":{
"color":"String",
"bold":boolean,
"itatic":boolean
}
}
}