|
|
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 };
|