ringcentral-personal-chatbot
Version:
RingCentral personal chatbot framework
294 lines (251 loc) • 7.77 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.subscribeInterval = exports.User = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _pick2 = _interopRequireDefault(require("lodash/pick"));
var _sequelize = _interopRequireDefault(require("sequelize"));
var _sequelize2 = _interopRequireDefault(require("./sequelize"));
var _timeoutAsPromise = _interopRequireDefault(require("timeout-as-promise"));
var _uid = _interopRequireDefault(require("../common/uid"));
var _constants = require("../common/constants");
var _buildTurnOffWarn = _interopRequireDefault(require("../common/build-turn-off-warn"));
var _sendMsg = require("../common/send-msg");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
const subscribeInterval = () => '/restapi/v1.0/subscription/~?threshold=120&interval=35';
exports.subscribeInterval = subscribeInterval;
const User = _sequelize2.default.define('user', {
id: {
type: _sequelize.default.STRING,
primaryKey: true,
defaultValue: _uid.default
},
name: {
type: _sequelize.default.STRING
},
firstName: {
type: _sequelize.default.STRING
},
lastName: {
type: _sequelize.default.STRING
},
email: {
type: _sequelize.default.STRING
},
timezone: {
type: _sequelize.default.JSON
},
turnOffDesc: {
type: _sequelize.default.STRING
},
token: {
type: _sequelize.default.JSON
},
enabled: {
type: _sequelize.default.BOOLEAN,
defaultValue: true
},
signed: {
type: _sequelize.default.BOOLEAN,
defaultValue: true
},
privateChatOnly: {
type: _sequelize.default.BOOLEAN,
defaultValue: false
},
lastUseTime: {
type: _sequelize.default.INTEGER
},
tokenUpdateTime: {
type: _sequelize.default.INTEGER
},
data: {
// all other data associcated with this user
type: _sequelize.default.JSON
}
});
exports.User = User;
User.init = async ({
code,
state
}) => {
const rc = await (0, _constants.createRc)();
await rc.authorize({
redirect_uri: rc.redirectUrl,
code
}).then(d => d.data);
const rcToken = rc.token;
const info = await rc.get('/restapi/v1.0/account/~/extension/~').then(r => r.data);
const {
timezone
} = (info === null || info === void 0 ? void 0 : info.regionalSettings) || {};
const rcId = rcToken.owner_id;
let user = await User.findByPk(rcId);
const now = Date.now();
const up = _objectSpread({
enabled: true,
token: rcToken,
timezone,
lastUseTime: now,
tokenUpdateTime: now,
name: info.name
}, (0, _pick2.default)(info.contact, ['firstName', 'lastName', 'email']));
const q = {
where: {
id: rcId
}
};
if (!user) {
user = await User.create(_objectSpread({
id: rcId
}, up));
} else {
Object.assign(user, up);
await User.update(up, q);
}
await user.ensureWebHook();
return rcId;
};
User.prototype.rc = async function () {
const rc = await (0, _constants.createRc)();
if (this.token) {
rc.token = this.token;
}
return rc;
};
User.prototype.removeWebHook = async function () {
return this.ensureWebHook(true);
};
User.prototype.ensureWebHook = async function (removeOnly = false) {
await this.tryRefresh();
const rc = await this.rc();
const r = await rc.get('/restapi/v1.0/subscription').then(d => d.data).catch(e => {
console.log(e, 'list WebHook error');
});
if (r && r.records) {
for (const sub of r.records) {
if (sub.deliveryMode.address === process.env.RINGCENTRAL_CHATBOT_SERVER + '/rc/webhook') {
await rc.delete(`/restapi/v1.0/subscription/${sub.id}`).catch(e => {
console.log(e, 'del WebHook error, id:', sub.id);
});
}
}
}
if (!removeOnly) {
return this.trySetupWebHook();
}
};
User.prototype.trySetupWebHook = async function () {
let count = 0;
let done = false;
while (count < 5 && !done) {
if (count > 0) {
console.log('retry setup webhook');
}
done = await this.setupWebHook();
count = count + 1;
await (0, _timeoutAsPromise.default)(1);
}
if (!done) {
await this.turnOff();
}
};
User.prototype.setupWebHook = async function () {
await this.tryRefresh();
const rc = await this.rc();
return rc.post('/restapi/v1.0/subscription', {
eventFilters: ['/restapi/v1.0/glip/posts', '/restapi/v1.0/glip/groups', subscribeInterval()],
expiresIn: 1799,
deliveryMode: {
transportType: 'WebHook',
address: process.env.RINGCENTRAL_CHATBOT_SERVER + '/rc/webhook'
}
}).then(() => true).catch(async e => {
console.log('setupWebHook error', e);
});
};
User.prototype.getSubscriptions = async function () {
await this.tryRefresh();
const rc = await this.rc();
return rc.get('/restapi/v1.0/subscription').then(d => d.data.records).catch(e => {
console.log('getSubscriptions error', e);
return [];
});
};
User.prototype.tryRefresh = async function () {
const now = Date.now();
const {
lastRefreshTime
} = this; // console.log('now', now)
// console.log('lastRefreshTime', lastRefreshTime)
// console.log('diff', now - lastRefreshTime)
// console.log('tokenExpireTime', tokenExpireTime)
if (now - lastRefreshTime < _constants.tokenExpireTime) {
return false;
}
return this.refresh();
};
User.prototype.refresh = async function () {
try {
const rc = await this.rc();
await rc.refresh();
const {
token
} = rc;
const now = Date.now();
const up = {
token,
lastRefreshTime: now
};
await User.update(up, {
where: {
id: this.id
}
});
Object.assign(this, up);
return true;
} catch (e) {
console.log('User refresh token error', e);
await this.turnOff();
console.log(`User ${this.id} refresh token has expired`);
return false;
}
};
User.prototype.turnOff = async function (groupId) {
if (!this.enabled) {
return 1;
}
const up = {
enabled: false,
turnOffDesc: 'fail'
};
await User.update(up, {
where: {
id: this.id
}
});
Object.assign(this, up);
const msg = await (0, _buildTurnOffWarn.default)(this);
await (0, _sendMsg.sendPrivateMsg)(this, msg);
};
User.prototype.getGroup = async function (groupId) {
await this.tryRefresh();
const rc = await this.rc();
return rc.get(`/restapi/v1.0/glip/groups/${groupId}`).then(d => d.data).catch(e => {
console.log('get group error', e);
return null;
});
};
User.prototype.sendMessage = async function (groupId, messageObj) {
await this.tryRefresh();
const rc = await this.rc();
const r = await rc.post(`/restapi/v1.0/glip/groups/${groupId}/posts`, messageObj).then(d => d.data).catch(err => {
console.log('send msg error', err);
});
return {
sendResult: r
};
};