bot proof of concept
This commit is contained in:
commit
ebc48141e2
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
config
|
||||
node_modules
|
||||
*.log
|
85
package.json
Normal file
85
package.json
Normal file
@ -0,0 +1,85 @@
|
||||
{
|
||||
"name": "ocrcc-bot",
|
||||
"version": "0.1.0",
|
||||
"description": "Chatbot to manage interactions on OCRCC client chatbots",
|
||||
"main": "dist/ocrcc-chatbot.js",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production webpack-cli --mode production",
|
||||
"start": "webpack-dev-server",
|
||||
"develop": "webpack --mode development --watch",
|
||||
"test": "jest",
|
||||
"lint": "./node_modules/.bin/eslint ."
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"config": "^3.2.5",
|
||||
"matrix-bot-sdk": "^0.5.0",
|
||||
"matrix-js-sdk": "^5.0.0",
|
||||
"node-localstorage": "^2.1.5",
|
||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",
|
||||
"uuidv4": "^6.0.2",
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.7.7",
|
||||
"@babel/plugin-proposal-class-properties": "7.7.4",
|
||||
"@babel/plugin-proposal-decorators": "7.7.4",
|
||||
"@babel/plugin-proposal-export-namespace-from": "7.7.4",
|
||||
"@babel/plugin-proposal-function-sent": "7.7.4",
|
||||
"@babel/plugin-proposal-json-strings": "7.7.4",
|
||||
"@babel/plugin-proposal-numeric-separator": "7.7.4",
|
||||
"@babel/plugin-proposal-throw-expressions": "7.7.4",
|
||||
"@babel/plugin-syntax-dynamic-import": "7.7.4",
|
||||
"@babel/plugin-syntax-import-meta": "7.7.4",
|
||||
"@storybook/addon-actions": "5.2.8",
|
||||
"@storybook/addon-links": "5.2.8",
|
||||
"@storybook/addons": "5.2.8",
|
||||
"@storybook/react": "5.2.8",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.0.3",
|
||||
"babel-jest": "24.9.0",
|
||||
"babel-loader": "8.0.6",
|
||||
"babel-preset-airbnb": "4.4.0",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"copy-webpack-plugin": "5.1.1",
|
||||
"enzyme": "3.11.0",
|
||||
"enzyme-adapter-react-16": "1.15.2",
|
||||
"enzyme-to-json": "3.4.3",
|
||||
"eslint": "6.8.0",
|
||||
"eslint-config-airbnb": "18.0.1",
|
||||
"eslint-import-resolver-webpack": "0.12.0",
|
||||
"eslint-loader": "3.0.3",
|
||||
"eslint-plugin-import": "2.19.1",
|
||||
"eslint-plugin-jsx-a11y": "6.2.3",
|
||||
"eslint-plugin-react": "7.17.0",
|
||||
"jest": "24.9.0",
|
||||
"jest-cli": "24.9.0",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "3.3.10",
|
||||
"webpack-dev-server": "3.10.1",
|
||||
"webpack-obfuscator": "0.22.0",
|
||||
"webpack-serve": "3.2.0"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"airbnb"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-syntax-import-meta",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-json-strings",
|
||||
[
|
||||
"@babel/plugin-proposal-decorators",
|
||||
{
|
||||
"legacy": true
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-function-sent",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-throw-expressions"
|
||||
]
|
||||
}
|
||||
}
|
153
src/index.js
Normal file
153
src/index.js
Normal file
@ -0,0 +1,153 @@
|
||||
const path = require("path")
|
||||
const fs = require("fs")
|
||||
const os = require("os")
|
||||
const util = require("util")
|
||||
|
||||
const config = require('config');
|
||||
const winston = require('winston');
|
||||
const uuid = require('uuidv4').uuid;
|
||||
const LocalStorage = require('node-localstorage').LocalStorage;
|
||||
global.Olm = require('olm');
|
||||
const matrix = require('matrix-js-sdk');
|
||||
const ENCRYPTION_CONFIG = { "algorithm": "m.megolm.v1.aes-sha2" };
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.json(),
|
||||
defaultMeta: { service: 'user-service' },
|
||||
transports: [
|
||||
//
|
||||
// - Write all logs with level `error` and below to `error.log`
|
||||
// - Write all logs with level `info` and below to `combined.log`
|
||||
//
|
||||
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
||||
new winston.transports.File({ filename: 'combined.log' })
|
||||
]
|
||||
});
|
||||
|
||||
//
|
||||
// If we're not in production then log to the `console` with the format:
|
||||
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
|
||||
//
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
logger.add(new winston.transports.Console({
|
||||
format: winston.format.simple()
|
||||
}));
|
||||
}
|
||||
|
||||
const homeserverUrl = 'https://matrix.rhok.space'
|
||||
const accessToken = 'MDAxOGxvY2F0aW9uIHJob2suc3BhY2UKMDAxM2lkZW50aWZpZXIga2V5CjAwMTBjaWQgZ2VuID0gMQowMDI3Y2lkIHVzZXJfaWQgPSBAaGVscC1ib3Q6cmhvay5zcGFjZQowMDE2Y2lkIHR5cGUgPSBhY2Nlc3MKMDAyMWNpZCBub25jZSA9IGZBOCsjWWQ4MF9LeTssaF8KMDAyZnNpZ25hdHVyZSA370YUvuoVD3r08AwdgGV9sE0aNWBRTrKvB1me8Bm0tQo'
|
||||
const botName = 'Help Bot'
|
||||
const username = 'help-bot'
|
||||
const password = 'ocrccdemo'
|
||||
const userId = "@help-bot:rhok.space"
|
||||
|
||||
let awaitingAgreement = {}
|
||||
|
||||
let client = matrix.createClient(homeserverUrl)
|
||||
|
||||
let localStorage = global.localStorage;
|
||||
if (typeof localStorage === "undefined" || localStorage === null) {
|
||||
const storageLoc = `matrix-chatbot-${username}`
|
||||
const dir = path.resolve(path.join(os.homedir(), ".local-storage"))
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
const localStoragePath = path.resolve(path.join(dir, storageLoc))
|
||||
localStorage = new LocalStorage(localStoragePath);
|
||||
}
|
||||
|
||||
let deviceId = localStorage.getItem('deviceId')
|
||||
|
||||
const sendMessage = (client, roomId, msgText) => {
|
||||
client.sendTextMessage(roomId, msgText)
|
||||
.then((res) => {
|
||||
logger.log('info', "Message sent")
|
||||
logger.log('info', res)
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.log('error', "Error sending message");
|
||||
logger.log('error', err);
|
||||
switch (err["name"]) {
|
||||
case "UnknownDeviceError":
|
||||
Object.keys(err.devices).forEach((userId) => {
|
||||
Object.keys(err.devices[userId]).map((deviceId) => {
|
||||
client.setDeviceVerified(userId, deviceId, true);
|
||||
});
|
||||
});
|
||||
sendMessage(client, roomId, msgText)
|
||||
break;
|
||||
default:
|
||||
// logger.log('error', err);
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const notifyFacilitators = (client, roomId) => {
|
||||
|
||||
}
|
||||
|
||||
client.login('m.login.password', {
|
||||
user: username,
|
||||
password: password,
|
||||
initial_device_display_name: botName,
|
||||
deviceId: deviceId,
|
||||
})
|
||||
.then((data) => {
|
||||
const accessToken = data.access_token
|
||||
const deviceId = data.device_id
|
||||
|
||||
localStorage.setItem('deviceId', data.device_id)
|
||||
// create new client with full options
|
||||
|
||||
let opts = {
|
||||
baseUrl: homeserverUrl,
|
||||
accessToken: accessToken,
|
||||
userId: userId,
|
||||
deviceId: deviceId,
|
||||
sessionStore: new matrix.WebStorageSessionStore(localStorage),
|
||||
}
|
||||
|
||||
client = matrix.createClient(opts)
|
||||
})
|
||||
.catch(err => {
|
||||
logger.log('error', `Login error: ${err}`)
|
||||
})
|
||||
.then(() => client.initCrypto())
|
||||
.then(() => {
|
||||
|
||||
// Automatically join all room invitations
|
||||
client.on("RoomMember.membership", (event, member) => {
|
||||
if (member.membership === "invite" && member.userId === userId) {
|
||||
client.joinRoom(member.roomId)
|
||||
.then(() => client.setRoomEncryption(member.roomId, ENCRYPTION_CONFIG))
|
||||
.then(() => {
|
||||
sendMessage(client, member.roomId, 'Do you want to continue?')
|
||||
awaitingAgreement[member.roomId] = true
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
client.on('Event.decrypted', (event) => {
|
||||
if (event.getType() === 'm.room.message') {
|
||||
const roomId = event.getRoomId()
|
||||
const sender = event.getSender()
|
||||
const content = event.getContent()
|
||||
const body = content.body
|
||||
|
||||
if (sender !== userId && awaitingAgreement[roomId]) {
|
||||
if (body.toLowerCase().startsWith('yes')) {
|
||||
sendMessage(client, roomId, "A facilitator will be with you soon.")
|
||||
notifyFacilitators(client, roomId)
|
||||
awaitingAgreement[roomId] = false
|
||||
} else {
|
||||
sendMessage(client, roomId, "Ok, bye")
|
||||
awaitingAgreement[roomId] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.finally(() => client.startClient())
|
||||
|
45
webpack.config.js
Normal file
45
webpack.config.js
Normal file
@ -0,0 +1,45 @@
|
||||
const JavaScriptObfuscator = require('webpack-obfuscator');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const path = require('path');
|
||||
|
||||
const devMode = process.env.NODE_ENV !== 'production';
|
||||
|
||||
const distDir = path.join(__dirname, 'dist');
|
||||
|
||||
const defaultConfig = {
|
||||
mode: process.env.NODE_ENV || 'development',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: ['babel-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'eslint-loader',
|
||||
options: {
|
||||
emitWarning: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['*', '.js'],
|
||||
},
|
||||
node: {
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = [{
|
||||
...defaultConfig,
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
path: distDir,
|
||||
filename: 'ocrcc-chatbot.js',
|
||||
},
|
||||
}];
|
Loading…
Reference in New Issue
Block a user