You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
7.4 KiB
187 lines
7.4 KiB
let fs = require('fs');
|
|
let sdk = require('matrix-js-sdk');
|
|
let message = require('./message');
|
|
let utility = require('./utility');
|
|
let { logger } = require('./logging');
|
|
|
|
class Bot {
|
|
constructor(config, buildInfo) {
|
|
this.config = config;
|
|
this.buildInfo = buildInfo;
|
|
this.connected = false;
|
|
}
|
|
|
|
/**
|
|
* Initialize the bot connection
|
|
*/
|
|
init(messageCallback) {
|
|
logger.info("Creating Matrix Client")
|
|
this.client = sdk.createClient({
|
|
baseUrl: this.config.baseUrl,
|
|
userId: this.config.userId
|
|
});
|
|
|
|
this.client.on("sync", async (state, previousState, data) => {
|
|
switch (state) {
|
|
case "PREPARED":
|
|
this.connected = true;
|
|
await this.sendStatusStartup();
|
|
await this.updateAvatar(process.env.NODE_PATH + '/assets/avatar.jpg');
|
|
this.client.getJoinedRooms()
|
|
.done((rooms) => {
|
|
logger.info("Connected to: %o", rooms)
|
|
});
|
|
break;
|
|
case "SYNCING":
|
|
logger.debug("Syncing")
|
|
break;
|
|
case "RECONNECTING":
|
|
logger.debug("Reconnecting");
|
|
break;
|
|
default:
|
|
logger.error("Unexpected sync state: %s", state);
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
this.client.on("RoomMember.membership", (event, member) => {
|
|
if (member.membership === "invite"
|
|
&& this.config.admin.indexOf(ember.userId) >= 0) {
|
|
this.client.joinRoom(member.roomId).done(() => {
|
|
logger.info("Auto-joined %s", member.roomId);
|
|
});
|
|
}
|
|
});
|
|
|
|
this.client.on("Room.timeline", messageCallback);
|
|
|
|
return this;
|
|
}
|
|
|
|
async connect() {
|
|
// logger.info("Initializing Crypto");
|
|
// await bot.client.initCrypto();
|
|
let botClient = this.client;
|
|
let botConfig = this.config;
|
|
|
|
let startServerConnection = () => {
|
|
logger.info("Starting Matrix SDK Client");
|
|
return this.client.startClient({
|
|
initialSyncLimit: 0
|
|
});
|
|
}
|
|
|
|
let attemptPasswordLogin = (botClient, botConfig) => {
|
|
return botClient.loginWithPassword(botConfig.userId, botConfig.userPassword)
|
|
.then((data) => {
|
|
logger.info("Successfully authenticated with password %o", data);
|
|
return startServerConnection();
|
|
}, (err) => {
|
|
logger.error("Failed to authenticate with password %o", err);
|
|
});
|
|
}
|
|
|
|
logger.info("Authenticating With Server");
|
|
if (typeof botConfig.accessToken !== 'undefined') {
|
|
await botClient.loginWithToken(this.config.accessToken)
|
|
.then((data) => {
|
|
logger.info("Successfully authenticated with access token %o", data);
|
|
return startServerConnection();
|
|
}, (err) => {
|
|
logger.error("Failed to authenticate with access token %o", err);
|
|
if (typeof botConfig.userPassword !== 'undefined') {
|
|
return attemptPasswordLogin(botClient, botConfig);
|
|
} else {
|
|
logger.error("No fallback password provided!");
|
|
}
|
|
});
|
|
} else if (typeof botConfig.userPassword !== 'undefined') {
|
|
await attemptPasswordLogin(botClient, botConfig);
|
|
} else {
|
|
logger.error("No authentication credentials available!");
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
updateAvatar(avatarFile, overwrite = false) {
|
|
let matrixClient = this.client;
|
|
let botConfig = this.config;
|
|
let promises = [Promise.resolve(true)];
|
|
if (this.connected) {
|
|
promises.push(this.client.getProfileInfo(this.config.userId, "avatar_url")
|
|
.then((existingAvatarUrl) => {
|
|
logger.info("Recieved avatar_url: %o", existingAvatarUrl);
|
|
if (typeof existingAvatarUrl !== 'undefined' && typeof existingAvatarUrl == 'object'
|
|
&& existingAvatarUrl.constructor === Object && Object.keys(existingAvatarUrl).length !== 0
|
|
&& !overwrite) {
|
|
logger.info("Avatar already set");
|
|
} else {
|
|
logger.info("Setting avatar content from %s", avatarFile);
|
|
let avatarFileBuffer = fs.readFileSync(avatarFile);
|
|
logger.debug("Avatar Image Data %o", avatarFileBuffer);
|
|
matrixClient.uploadContent(avatarFileBuffer, {
|
|
name: botConfig.userId + " avatar",
|
|
type: "image/jpeg",
|
|
rawResponse: false
|
|
}).then((uploadedAvatar) => {
|
|
logger.info("Uploaded avatar %o", uploadedAvatar);
|
|
matrixClient.setAvatarUrl(uploadedAvatar.content_uri)
|
|
.then(() => {
|
|
logger.info("Updated %s avatar to %s", botConfig.userId, uploadedAvatar.content_uri);
|
|
return true;
|
|
});
|
|
});
|
|
}
|
|
}));
|
|
} else {
|
|
logger.warn("Attempting to update avatar while disconnected");
|
|
}
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
sendStatusStartup() {
|
|
let promises = [Promise.resolve(true)]
|
|
if (this.connected) {
|
|
this.config.statusRooms.forEach(roomId => {
|
|
logger.debug("Notifying %s of startup", roomId);
|
|
promises.push(this.client.sendMessage(
|
|
roomId, message.createBasic("Started with version: " + this.buildInfo, message.types.NOTICE)
|
|
).then(() => {
|
|
logger.debug("Notified %s of startup", roomId);
|
|
}, (err) => {
|
|
logger.error("Unable to send message to room %s because %s", roomId, err.errcode);
|
|
}));
|
|
});
|
|
} else {
|
|
logger.warn("Attempting to send startup message while disconnected");
|
|
}
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
sendStatusShutdown() {
|
|
let promises = [Promise.resolve(true)]
|
|
if (this.connected) {
|
|
this.config.statusRooms.forEach(roomId => {
|
|
logger.debug("Notifying %s of shutdown", roomId);
|
|
promises.push(this.client.sendMessage(
|
|
roomId, message.createBasic("Shutting down", message.types.NOTICE)
|
|
).then(() => {
|
|
logger.debug("Notified %s of shutdown", roomId);
|
|
}, (err) => {
|
|
logger.error("Unable to send message to room %s because %s", roomId, err.errcode);
|
|
}));
|
|
});
|
|
} else {
|
|
logger.warn("Attempting to send shutdown message while disconnected");
|
|
}
|
|
return Promise.all(promises);
|
|
}
|
|
}
|
|
|
|
function create(config) {
|
|
let buildInfo = utility.getBuildInfo();
|
|
logger.info("Running version: %s", buildInfo);
|
|
return new Bot(config, buildInfo);
|
|
}
|
|
|
|
exports.create = create;
|