Baphomet is the dedicated bot for nulloctet matrix
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.
 
 
 
 
 

195 lines
7.7 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 {
client: any;
config: any;
buildInfo: string;
connected: boolean;
startTime: Date;
constructor(config, buildInfo) {
this.config = config;
this.buildInfo = buildInfo;
this.connected = false;
this.startTime = new Date();
}
/**
* Initialize the bot connection
*/
init(messageCallback: any) {
logger.info("Creating Matrix Client")
this.client = sdk.createClient({
baseUrl: this.config.baseUrl,
userId: this.config.userId
});
this.client.on("sync", async (state: any, previousState: any, data: any) => {
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: any, member: any) => {
if (member.membership === "invite"
&& this.config.admin.indexOf(member.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 at ${utility.toISODateString(this.startTime)} 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 at ${utility.toISODateString(new Date())} with version: ${this.buildInfo}`, 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);
}
export { create };